Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make DynamicMessage public #753

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nerodesu017
Copy link

This PR aims to help with decoding dynamic messages.
Encoding is already supported, but decoding is not so straight-forward and to actually get any field's value, you would need to downcast the Box<dyn Message> that you decode into the actual FullMessage that you do not have, as you have to do it at runtime.

The next example exemplifies this:

#[test]
fn test_decode_dynamic_message() {
    use protobuf::descriptor::FileDescriptorProto;
    use protobuf::{
        self,
        reflect::{dynamic::DynamicMessage, FileDescriptor},
    };

    // Hello markus
    let bytes: Vec<u8> = vec![
        10, 12, 72, 101, 108, 108, 111, 32, 109, 97, 114, 107, 117, 115,
    ];

    let message_proto = r#"
syntax = "proto3";
message Message {
  string message = 1;
}
"#;

    let temp_dir = tempfile::tempdir().unwrap();
    let tempfile = temp_dir.path().join("CUSTOM_FILE.proto");
    std::fs::write(&tempfile, message_proto).unwrap();
    let mut file_descriptor_protos = protobuf_parse::Parser::new()
        .pure()
        .includes(&[temp_dir.path().to_path_buf()])
        .input(&tempfile)
        .parse_and_typecheck()
        .unwrap()
        .file_descriptors;

    let file_descriptor_proto: FileDescriptorProto = file_descriptor_protos.pop().unwrap();
    let file_descriptor: FileDescriptor =
        FileDescriptor::new_dynamic(file_descriptor_proto, &[]).unwrap();

    let msg_descriptor = file_descriptor
        .message_by_package_relative_name("Message")
        .unwrap();

    let msg = msg_descriptor.parse_from_bytes(&bytes).unwrap();

    // we need DynamicMessage public so that we can cast it here
    let dynamic_msg = msg.downcast_box::<DynamicMessage>().unwrap();

    let field_ref = dynamic_msg.get_reflect(&msg_descriptor.field_by_name("message").unwrap());
    if let protobuf::reflect::ReflectFieldRef::Optional(field) = field_ref {
        println!("{:?}", field.value()); // <- this prints 'Some(String("Hello markus"))'
    };
}

@nerodesu017 nerodesu017 force-pushed the nero/dev/dynamic_message_decoding branch 2 times, most recently from 1c74f81 to cd27fed Compare January 17, 2025 20:36
@nerodesu017 nerodesu017 force-pushed the nero/dev/dynamic_message_decoding branch from cd27fed to a125197 Compare January 18, 2025 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant