msg_tool\utils/
struct_pack.rs

1//! Binary Struct Packing and Unpacking Utilities
2use crate::types::Encoding;
3use anyhow::Result;
4use msg_tool_macro::struct_unpack_impl_for_num;
5use std::any::Any;
6use std::io::{Read, Seek, Write};
7
8/// Trait for unpacking a struct from a binary stream.
9pub trait StructUnpack: Sized {
10    /// Unpacks a struct from a binary stream.
11    ///
12    /// * `reader` - The reader to read the binary data from.
13    /// * `big` - Whether the data is in big-endian format.
14    /// * `encoding` - The encoding to use for string fields.
15    /// * `info` - Additional information that may be needed for unpacking.
16    fn unpack<R: Read + Seek>(
17        reader: &mut R,
18        big: bool,
19        encoding: Encoding,
20        info: &Option<Box<dyn Any>>,
21    ) -> Result<Self>;
22}
23
24/// Trait for packing a struct into a binary stream.
25pub trait StructPack: Sized {
26    /// Packs a struct into a binary stream.
27    ///
28    /// * `writer` - The writer to write the binary data to.
29    /// * `big` - Whether to use big-endian format.
30    /// * `encoding` - The encoding to use for string fields.
31    /// * `info` - Additional information that may be needed for packing.
32    fn pack<W: Write>(
33        &self,
34        writer: &mut W,
35        big: bool,
36        encoding: Encoding,
37        info: &Option<Box<dyn Any>>,
38    ) -> Result<()>;
39}
40
41impl<T: StructPack> StructPack for Vec<T> {
42    fn pack<W: Write>(
43        &self,
44        writer: &mut W,
45        big: bool,
46        encoding: Encoding,
47        info: &Option<Box<dyn Any>>,
48    ) -> Result<()> {
49        for item in self {
50            item.pack(writer, big, encoding, info)?;
51        }
52        Ok(())
53    }
54}
55
56struct_unpack_impl_for_num!(u8);
57struct_unpack_impl_for_num!(u16);
58struct_unpack_impl_for_num!(u32);
59struct_unpack_impl_for_num!(u64);
60struct_unpack_impl_for_num!(u128);
61struct_unpack_impl_for_num!(i8);
62struct_unpack_impl_for_num!(i16);
63struct_unpack_impl_for_num!(i32);
64struct_unpack_impl_for_num!(i64);
65struct_unpack_impl_for_num!(i128);
66struct_unpack_impl_for_num!(f32);
67struct_unpack_impl_for_num!(f64);
68
69impl StructUnpack for bool {
70    fn unpack<R: Read + Seek>(
71        reader: &mut R,
72        _big: bool,
73        _encoding: Encoding,
74        _info: &Option<Box<dyn Any>>,
75    ) -> Result<Self> {
76        let mut buf = [0u8; 1];
77        reader.read_exact(&mut buf)?;
78        Ok(buf[0] != 0)
79    }
80}
81
82impl StructPack for bool {
83    fn pack<W: Write>(
84        &self,
85        writer: &mut W,
86        _big: bool,
87        _encoding: Encoding,
88        _info: &Option<Box<dyn Any>>,
89    ) -> Result<()> {
90        writer.write_all(&[if *self { 1 } else { 0 }])?;
91        Ok(())
92    }
93}
94
95impl<T: StructPack> StructPack for Option<T> {
96    fn pack<W: Write>(
97        &self,
98        writer: &mut W,
99        big: bool,
100        encoding: Encoding,
101        info: &Option<Box<dyn Any>>,
102    ) -> Result<()> {
103        if let Some(value) = self {
104            value.pack(writer, big, encoding, info)?;
105        }
106        Ok(())
107    }
108}
109
110impl<T: StructUnpack> StructUnpack for Option<T> {
111    fn unpack<R: Read + Seek>(
112        reader: &mut R,
113        big: bool,
114        encoding: Encoding,
115        info: &Option<Box<dyn Any>>,
116    ) -> Result<Self> {
117        let value = T::unpack(reader, big, encoding, info)?;
118        Ok(Some(value))
119    }
120}
121
122impl<const T: usize> StructPack for [u8; T] {
123    fn pack<W: Write>(
124        &self,
125        writer: &mut W,
126        _big: bool,
127        _encoding: Encoding,
128        _info: &Option<Box<dyn Any>>,
129    ) -> Result<()> {
130        writer.write_all(self)?;
131        Ok(())
132    }
133}
134
135impl<const T: usize> StructUnpack for [u8; T] {
136    fn unpack<R: Read + Seek>(
137        reader: &mut R,
138        _big: bool,
139        _encoding: Encoding,
140        _info: &Option<Box<dyn Any>>,
141    ) -> Result<Self> {
142        let mut buf = [0u8; T];
143        reader.read_exact(&mut buf)?;
144        Ok(buf)
145    }
146}