diff --git a/Cargo.lock b/Cargo.lock index e61b42c..a64917c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,9 +6,16 @@ version = 3 name = "anybuf" version = "0.5.2" dependencies = [ + "bytes", "hex-literal", ] +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + [[package]] name = "hex-literal" version = "0.4.1" diff --git a/Cargo.toml b/Cargo.toml index b2975e9..671b7e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,4 @@ std = [] [dev-dependencies] hex-literal = "0.4.1" +bytes = "1.10.1" diff --git a/src/anybuf.rs b/src/anybuf.rs index 619eca4..d2e3adf 100644 --- a/src/anybuf.rs +++ b/src/anybuf.rs @@ -21,7 +21,7 @@ enum WireType { } /// A minmal protobuf encoder. -#[derive(Default)] +#[derive(Default, Clone)] pub struct Anybuf { output: Vec, } @@ -519,6 +519,35 @@ impl Anybuf { self.output } + /// Takes the instance and returns the protobuf bytes. + /// The return type is defined by the caller and can be anything that implements `From>`. + /// Roughly speaking, `data.into_x()` is the same as calling `data.into_vec().into()`. + /// + /// ## Examples + /// + /// We create an Anybuf instance and then convert it into [Bytes], which just serves + /// as an example for a type that can be created from `Vec`. + /// + /// ``` + /// # use anybuf::Anybuf; + /// use bytes::Bytes; + /// + /// // variable type known + /// let serialized: Bytes = Anybuf::new() + /// .append_repeated_int64(4, &[-30, 0, 17]) + /// .into_x(); + /// + /// // explicit type parameter + /// let serialized = Anybuf::new() + /// .append_repeated_int64(4, &[-30, 0, 17]) + /// .into_x::(); + /// ``` + /// + /// [Bytes]: https://docs.rs/bytes/latest/bytes/struct.Bytes.html + pub fn into_x>>(self) -> T { + T::from(self.output) + } + fn append_tag(&mut self, field_number: u32, field_type: WireType) { // The top 3 bits of a field number must be unset, ie.e this shift is safe for valid field numbers // "The smallest field number you can specify is 1, and the largest is 2^29-1, or 536,870,911" @@ -1027,4 +1056,24 @@ mod tests { let data = Anybuf::new().append_repeated_message(11, &owned); assert_eq!(data.into_vec(), hex!("5a0208015a0208025a020803")); } + + #[test] + fn into_x_works() { + use bytes::Bytes; + + let data = Anybuf::new() + .append_string(1, "hello, world") + .append_repeated_int64(2, &[-30, 0, 17]); + let vec = data.clone().into_vec(); + let bytes: Bytes = data.into_x(); + assert_eq!(bytes, vec); + + let serialized = Anybuf::new() + .append_repeated_int64(4, &[-30, 0, 17]) + .into_x::(); + assert_eq!( + serialized, + b" \xe2\xff\xff\xff\xff\xff\xff\xff\xff\x01 \0 \x11" as &[u8] + ); + } }