aikalant / capnp_conv

MIT License
11 stars 4 forks source link

Easy conversion to/from binary format #5

Open jackbackes opened 2 months ago

jackbackes commented 2 months ago

I found these auto-implemented traits useful for easy conversion to-and-from capnp format. If this aligns with the direction you might want to go, I'm happy to raise a PR:


trait CapnpSerlializable {
    fn to_capnp_bin(&self) -> Vec<u8>;
}

trait CapnpDeserializable {
    fn from_capnp_bin(bytes: &[u8]) -> Self;
}

impl<T> CapnpSerlializable for T
where
    T: Writable,
{
    fn to_capnp_bin(&self) -> Vec<u8> {
        let mut builder = capnp::message::TypedBuilder::<T::OwnedType>::new_default(); // For Writable
        let root = builder.init_root();
        self.write(root);

        let mut message_bin: Vec<u8> = Vec::new();
        let send_builder: capnp::message::Builder<_> = builder.into_inner();
        capnp::serialize::write_message(&mut message_bin, &send_builder).unwrap();

        message_bin
    }
}

impl<T> CapnpDeserializable for T
where
    T: Readable,
{
    fn from_capnp_bin(bytes: &[u8]) -> Self {
        let message_reader = capnp::serialize::read_message(
            &mut std::io::Cursor::new(bytes),
            capnp::message::ReaderOptions::new(),
        ).unwrap();

        let reader = message_reader.get_root().unwrap();
        Self::read(reader).unwrap()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test() {
        let example = ExampleRequest {
            user_id: 1,
        };

        let example_bin = example.to_capnp_bin();
        let example_2: ExampleRequest = ExampleRequest::from_capnp_bin(example_bin.as_slice());

        assert_eq!(example, example_2);
    }
}