jute/code_generator/rust/
mod.rs

1use std::{
2    cmp::max,
3    collections::HashMap,
4    hash::Hash,
5    io::{Read, Write},
6};
7
8use crate::errors::JuteError;
9
10pub(crate) mod utilities;
11pub(crate) mod writer;
12
13/// Trait for types that can be serialized to and deserialized from
14/// the Jute binary encoding format.
15///
16/// `JuteSerializable` is implemented by all structs generated from
17/// Jute schema files. It provides low-level, streaming-based
18/// serialization and deserialization APIs that follow the
19/// Apache Jute wire format.
20///
21/// # Design
22///
23/// - Serialization writes data sequentially to any [`Write`] implementation
24///   (for example `Vec<u8>`, `File`, or `TcpStream`).
25/// - Deserialization reads data sequentially from any [`Read`] implementation.
26/// - No buffering is performed internally; callers may wrap streams in
27///   buffered readers or writers if needed.
28///
29/// This design allows Jute-generated types to be used efficiently in
30/// both file-based and network-based protocols.
31///
32/// # Example
33///
34/// ``` no_run
35/// use std::io::Cursor;
36/// use jute::JuteSerializable;
37///
38/// // x can be of any type that implement JuteSerializable
39/// let x = "test".to_string();
40///
41/// // Serialize into a byte buffer
42/// let mut buffer = Vec::new();
43/// x.serialize(&mut buffer).unwrap();
44///
45/// // Deserialize from the buffer
46/// let mut cursor = Cursor::new(buffer);
47/// let x = String::deserialize(&mut cursor).unwrap();
48/// ```
49///
50/// # Errors
51///
52/// Both serialization and deserialization return [`JuteError`] if:
53///
54/// - An I/O error occurs while reading or writing
55/// - The input stream is malformed or truncated
56/// - The encoded data violates the Jute type rules
57///
58/// # Notes
59///
60/// - Implementations must read and write fields in the exact order
61///   defined in the Jute schema.
62/// - The `deserialize` method assumes the input stream is positioned
63///   at the start of a valid Jute-encoded value.
64///
65/// [`Read`]: std::io::Read
66/// [`Write`]: std::io::Write
67pub trait JuteSerializable: Sized {
68    /// Serializes `self` into the given output stream using
69    /// the Jute binary encoding format.
70    ///
71    /// Implementations must write fields in schema order.
72    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError>;
73    /// Deserializes a value of this type from the given input stream
74    /// using the Jute binary encoding format.
75    ///
76    /// The stream must be positioned at the start of a valid
77    /// encoded value.
78    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError>;
79}
80
81impl JuteSerializable for i32 {
82    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
83        out.write_all(&self.to_be_bytes())?;
84        Ok(())
85    }
86    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
87        let mut arr = [0u8; 4];
88        bytes.read_exact(&mut arr)?;
89        Ok(i32::from_be_bytes(arr))
90    }
91}
92
93impl JuteSerializable for i64 {
94    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
95        out.write_all(&self.to_be_bytes())?;
96        Ok(())
97    }
98
99    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
100        let mut arr = [0u8; 8];
101        bytes.read_exact(&mut arr)?;
102        Ok(i64::from_be_bytes(arr))
103    }
104}
105
106impl JuteSerializable for f32 {
107    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
108        out.write_all(&self.to_be_bytes())?;
109        Ok(())
110    }
111    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
112        let mut arr = [0u8; 4];
113        bytes.read_exact(&mut arr)?;
114        Ok(f32::from_be_bytes(arr))
115    }
116}
117
118impl JuteSerializable for f64 {
119    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
120        out.write_all(&self.to_be_bytes())?;
121
122        Ok(())
123    }
124    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
125        let mut arr = [0u8; 8];
126        bytes.read_exact(&mut arr)?;
127        Ok(f64::from_be_bytes(arr))
128    }
129}
130
131impl JuteSerializable for bool {
132    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
133        out.write_all(if *self { &[0x01] } else { &[0x00] })?;
134        Ok(())
135    }
136    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
137        let mut byte = [0u8; 1];
138        bytes.read_exact(&mut byte)?;
139        Ok(byte[0] != 0)
140    }
141}
142
143impl JuteSerializable for u8 {
144    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
145        out.write_all(&self.to_be_bytes())?;
146        Ok(())
147    }
148    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
149        let mut byte = [0u8; 1];
150        bytes.read_exact(&mut byte)?;
151        Ok(byte[0])
152    }
153}
154impl<T> JuteSerializable for Vec<T>
155where
156    T: JuteSerializable,
157{
158    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
159        let elem_count = self.len() as i32;
160        out.write_all(&elem_count.to_be_bytes())?;
161        for elem in self {
162            elem.serialize(out)?;
163        }
164        Ok(())
165    }
166    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
167        let mut arr = [0u8; 4];
168        bytes.read_exact(&mut arr)?;
169        let elem_count = max(i32::from_be_bytes(arr), 0) as usize;
170        let mut vec = Vec::<T>::with_capacity(elem_count);
171        for _i in 0..elem_count {
172            vec.push(T::deserialize(bytes)?);
173        }
174        Ok(vec)
175    }
176}
177impl JuteSerializable for String {
178    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
179        let bytes = self.as_bytes();
180        out.write_all(&(bytes.len() as i32).to_be_bytes())?;
181        out.write_all(bytes)?;
182        Ok(())
183    }
184    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
185        let mut arr = [0u8; 4];
186        bytes.read_exact(&mut arr)?;
187        let elem_count = max(i32::from_be_bytes(arr), 0) as usize;
188
189        let mut buffer = vec![0u8; elem_count];
190        bytes.read_exact(&mut buffer)?;
191        let result = String::from_utf8(buffer)?;
192        Ok(result)
193    }
194}
195impl<T, U> JuteSerializable for HashMap<T, U>
196where
197    T: JuteSerializable + Hash + Eq,
198    U: JuteSerializable,
199{
200    fn serialize<W: Write>(&self, out: &mut W) -> Result<(), JuteError> {
201        let elem_count = self.len() as i32;
202        out.write_all(&elem_count.to_be_bytes())?;
203        for (key, value) in self {
204            key.serialize(out)?;
205            value.serialize(out)?;
206        }
207        Ok(())
208    }
209    fn deserialize<R: Read>(bytes: &mut R) -> Result<Self, JuteError> {
210        let mut arr = [0u8; 4];
211        bytes.read_exact(&mut arr)?;
212        let elem_count = max(i32::from_be_bytes(arr), 0) as usize;
213        let mut map = HashMap::<T, U>::with_capacity(elem_count);
214        for _i in 0..elem_count {
215            map.insert(T::deserialize(bytes)?, U::deserialize(bytes)?);
216        }
217        Ok(map)
218    }
219}
220
221#[cfg(test)]
222mod tests {
223    use super::*;
224
225    fn roundtrip<T: JuteSerializable + PartialEq + std::fmt::Debug>(value: T) {
226        let mut buf = vec![];
227        value.serialize(&mut buf).unwrap();
228
229        let mut cursor = std::io::Cursor::new(buf);
230        let decoded = T::deserialize(&mut cursor).unwrap();
231
232        assert_eq!(value, decoded);
233    }
234
235    #[test]
236    fn test_i32() {
237        roundtrip(123i32);
238        roundtrip(-999i32);
239    }
240
241    #[test]
242    fn test_string() {
243        roundtrip("hello".to_string());
244        roundtrip("".to_string());
245    }
246
247    #[test]
248    fn test_bool() {
249        roundtrip(true);
250        roundtrip(false);
251    }
252
253    #[test]
254    fn test_vec() {
255        roundtrip(vec![1i32, 2, 3]);
256        roundtrip::<Vec<i32>>(vec![]);
257    }
258
259    #[test]
260    fn test_map() {
261        let mut m = HashMap::new();
262        m.insert("a".to_string(), 1i32);
263        m.insert("b".to_string(), 2i32);
264        roundtrip(m);
265    }
266}