#protobuf #serialization #codec #json #serde-json #file-descriptor #descriptor-set

prost-reflect-build

A utility function for use with prost-build and prost-reflect to generate ReflectMessage implementations

8 breaking releases

0.14.0 Jul 8, 2024
0.13.0 Feb 7, 2024
0.12.0 Sep 1, 2023
0.11.0 Mar 27, 2023
0.6.0 Mar 14, 2022

#667 in Encoding

Download history 4789/week @ 2024-07-15 5150/week @ 2024-07-22 4886/week @ 2024-07-29 5063/week @ 2024-08-05 5954/week @ 2024-08-12 5099/week @ 2024-08-19 5096/week @ 2024-08-26 4739/week @ 2024-09-02 4442/week @ 2024-09-09 4899/week @ 2024-09-16 5483/week @ 2024-09-23 6326/week @ 2024-09-30 6533/week @ 2024-10-07 6017/week @ 2024-10-14 7287/week @ 2024-10-21 6246/week @ 2024-10-28

26,247 downloads per month
Used in 20 crates (4 directly)

MIT/Apache

550KB
12K SLoC

crates.io docs.rs deps.rs MSRV Continuous integration codecov.io Apache 2.0 OR MIT licensed

prost-reflect

A protobuf library extending prost with reflection support and dynamic messages.

Usage

This crate provides support for dynamic protobuf messages. These are useful when the protobuf type definition is not known ahead of time.

The main entry points into the API of this crate are:

Example - decoding

DynamicMessage does not implement Default since it needs a message descriptor to function. To decode a protobuf byte stream into an instance of this type, use DynamicMessage::decode to create a default value for the MessageDescriptor instance and merge into it:

use prost::Message;
use prost_types::FileDescriptorSet;
use prost_reflect::{DynamicMessage, DescriptorPool, Value};

let pool = DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap();
let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap();

let dynamic_message = DynamicMessage::decode(message_descriptor, b"\x08\x96\x01".as_ref()).unwrap();

assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150));

Example - JSON mapping

When the serde feature is enabled, DynamicMessage can be deserialized to and from the canonical JSON mapping defined for protobuf messages.

use prost::Message;
use prost_reflect::{DynamicMessage, DescriptorPool, Value};
use serde_json::de::Deserializer;

let pool = DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap();
let message_descriptor = pool.get_message_by_name("package.MyMessage").unwrap();

let json = r#"{ "foo": 150 }"#;
let mut deserializer = Deserializer::from_str(json);
let dynamic_message = DynamicMessage::deserialize(message_descriptor, &mut deserializer).unwrap();
deserializer.end().unwrap();

assert_eq!(dynamic_message.get_field_by_name("foo").unwrap().as_ref(), &Value::I32(150));

Example - implementing ReflectMessage

The ReflectMessage trait provides a .descriptor() method to get type information for a message. It is implemented for DynamicMessage and the well-known-types provided by prost-types.

When the derive feature is enabled, it can be derived for Message implementations. The derive macro takes the following parameters:

Name Value
descriptor_pool An expression that resolves to a DescriptorPool containing the message type. The descriptor should be cached to avoid re-building it. Either this or file_descriptor_pool_bytes must be set
file_descriptor_pool_bytes An expression that resolves to an implementation of Buf containing an encoded file descriptor set. This will be automatically added to the global descriptor pool the first time ReflectMessage::descriptor() is called.
message_name The full name of the message, used to look it up within DescriptorPool.
use prost::Message;
use prost_reflect::{DescriptorPool, ReflectMessage};
use once_cell::sync::Lazy;

static DESCRIPTOR_POOL: Lazy<DescriptorPool>
    = Lazy::new(|| DescriptorPool::decode(include_bytes!("file_descriptor_set.bin").as_ref()).unwrap());

#[derive(Message, ReflectMessage)]
#[prost_reflect(descriptor_pool = "DESCRIPTOR_POOL", message_name = "package.MyMessage")]
pub struct MyMessage {}

let message = MyMessage {};
assert_eq!(message.descriptor().full_name(), "package.MyMessage");

If you are using prost-build, the prost-reflect-build crate provides helpers to generate ReflectMessage implementations:

prost_reflect_build::Builder::new()
    .compile_protos(&["src/package.proto"], &["src"])
    .unwrap();

Minimum Supported Rust Version

Rust 1.64 or higher.

The minimum supported Rust version may be changed in the future, but it will be done with a minor version bump.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~8–18MB
~249K SLoC