Skip to main content

protocol_message/
protocol_message.rs

1use reliakit_codec::{
2    decode_from_slice_exact, encode_to_vec, CanonicalDecode, CanonicalEncode, CodecError,
3    CodecErrorKind, DecodeSource, EncodeSink,
4};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7struct ProtocolMessage {
8    id: u32,
9    kind: MessageKind,
10}
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13enum MessageKind {
14    Ping,
15    Data(Vec<u8>),
16}
17
18impl CanonicalEncode for ProtocolMessage {
19    fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
20        self.id.encode(writer)?;
21        self.kind.encode(writer)
22    }
23}
24
25impl CanonicalDecode for ProtocolMessage {
26    fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
27        Ok(Self {
28            id: u32::decode(reader)?,
29            kind: MessageKind::decode(reader)?,
30        })
31    }
32}
33
34impl CanonicalEncode for MessageKind {
35    fn encode<W: EncodeSink + ?Sized>(&self, writer: &mut W) -> Result<(), CodecError> {
36        match self {
37            Self::Ping => 0u8.encode(writer),
38            Self::Data(bytes) => {
39                1u8.encode(writer)?;
40                bytes.encode(writer)
41            }
42        }
43    }
44}
45
46impl CanonicalDecode for MessageKind {
47    fn decode<R: DecodeSource + ?Sized>(reader: &mut R) -> Result<Self, CodecError> {
48        match u8::decode(reader)? {
49            0 => Ok(Self::Ping),
50            1 => Vec::<u8>::decode(reader).map(Self::Data),
51            _ => Err(CodecError::invalid_value(
52                "unknown MessageKind tag: expected 0x00 or 0x01",
53            )),
54        }
55    }
56}
57
58fn main() -> Result<(), CodecError> {
59    let message = ProtocolMessage {
60        id: 42,
61        kind: MessageKind::Data(vec![1, 2, 3]),
62    };
63
64    let encoded = encode_to_vec(&message)?;
65    assert_eq!(encoded, [42, 0, 0, 0, 1, 3, 0, 0, 0, 1, 2, 3]);
66    assert_eq!(
67        decode_from_slice_exact::<ProtocolMessage>(&encoded)?,
68        message
69    );
70
71    let err = decode_from_slice_exact::<MessageKind>(&[9]).unwrap_err();
72    assert_eq!(err.kind(), CodecErrorKind::InvalidValue);
73    assert!(err.message().contains("unknown MessageKind tag"));
74
75    Ok(())
76}