titan-api-codec 1.2.9

Helpers for encoding and decoding Titan API messages
Documentation
//! Implementing encoding support for the [MessagePack] format.
//!
//! [MessagePack]: https://msgpack.org/index.html

use super::common::{EncodeError, Encoder};

use bytes::{BufMut, Bytes, BytesMut};
use rmp_serde::encode::Serializer;

/// Encodes messages to MessagePack binary format.
#[derive(Default)]
pub struct MessagePackEncoder {}

impl Encoder for MessagePackEncoder {
    fn encode<T>(&self, value: &T) -> Result<Bytes, EncodeError>
    where
        T: serde::Serialize,
    {
        let mut buffer = BytesMut::new().writer();
        let mut serializer = Serializer::new(&mut buffer).with_struct_map();
        value
            .serialize(&mut serializer)
            .map_err(|err| EncodeError::SerializationFailed(Box::new(err)))?;
        Ok(buffer.into_inner().freeze())
    }
}

#[cfg(test)]
mod test {
    use super::MessagePackEncoder;
    use crate::enc::Encoder;

    use bytes::Bytes;
    use hex_literal::hex;

    // Equivalent to TestStruct { a: 1234, b: "hello", c: [1, 2, 3, 4] }
    const TEST_STRUCT_PACKED_NAMED: [u8; 22] = hex!("83a161cd04d2a162a568656c6c6fa163c40401020304");

    #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
    struct TestStruct {
        a: u32,
        b: String,
        #[serde(with = "serde_bytes")]
        c: Vec<u8>,
    }

    #[test]
    fn test_encode() {
        let test = TestStruct {
            a: 1234,
            b: "hello".into(),
            c: vec![1, 2, 3, 4],
        };
        let encoder = MessagePackEncoder::default();

        let encoded = encoder.encode(&test).expect("should encode to messagepack");
        let expected = Bytes::from_static(&TEST_STRUCT_PACKED_NAMED);
        assert_eq!(encoded, expected);
    }
}