Skip to main content

basalt_types/
traits.rs

1use crate::Result;
2
3/// Serialize a value into a byte buffer.
4pub trait Encode {
5    fn encode(&self, buf: &mut Vec<u8>) -> Result<()>;
6}
7
8/// Deserialize a value from a byte slice, advancing the cursor.
9pub trait Decode: Sized {
10    fn decode(buf: &mut &[u8]) -> Result<Self>;
11}
12
13/// Predict the exact serialized byte count for pre-allocation.
14pub trait EncodedSize {
15    fn encoded_size(&self) -> usize;
16}
17
18// Blanket `Encode` / `Decode` / `EncodedSize` impls for `Box<T>`.
19//
20// The codegen wraps recursive struct/variant fields in `Box` to break
21// the infinite-size cycle (e.g. `SlotDisplay::SmithingTrim { base:
22// Box<SlotDisplay> }`). The wire format is identical to the inner
23// `T`'s — `Box` is a Rust-side concern only — so we forward to `T`
24// through a deref.
25
26impl<T: Encode + ?Sized> Encode for Box<T> {
27    fn encode(&self, buf: &mut Vec<u8>) -> Result<()> {
28        (**self).encode(buf)
29    }
30}
31
32impl<T: Decode> Decode for Box<T> {
33    fn decode(buf: &mut &[u8]) -> Result<Self> {
34        T::decode(buf).map(Box::new)
35    }
36}
37
38impl<T: EncodedSize + ?Sized> EncodedSize for Box<T> {
39    fn encoded_size(&self) -> usize {
40        (**self).encoded_size()
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use crate::Error;
48
49    /// Dummy type to verify the traits compile and work together.
50    struct DummyByte(u8);
51
52    impl Encode for DummyByte {
53        fn encode(&self, buf: &mut Vec<u8>) -> Result<()> {
54            buf.push(self.0);
55            Ok(())
56        }
57    }
58
59    impl Decode for DummyByte {
60        fn decode(buf: &mut &[u8]) -> Result<Self> {
61            if buf.is_empty() {
62                return Err(Error::BufferUnderflow {
63                    needed: 1,
64                    available: 0,
65                });
66            }
67            let value = buf[0];
68            *buf = &buf[1..];
69            Ok(DummyByte(value))
70        }
71    }
72
73    impl EncodedSize for DummyByte {
74        fn encoded_size(&self) -> usize {
75            1
76        }
77    }
78
79    #[test]
80    fn roundtrip() {
81        let original = DummyByte(42);
82        let mut buf = Vec::with_capacity(original.encoded_size());
83        original.encode(&mut buf).unwrap();
84        assert_eq!(buf.len(), original.encoded_size());
85
86        let mut cursor = buf.as_slice();
87        let decoded = DummyByte::decode(&mut cursor).unwrap();
88        assert_eq!(decoded.0, 42);
89        assert!(cursor.is_empty());
90    }
91
92    #[test]
93    fn decode_empty_buffer() {
94        let mut cursor: &[u8] = &[];
95        let result = DummyByte::decode(&mut cursor);
96        assert!(result.is_err());
97    }
98}