justcode_core/
writer.rs

1//! Writer for encoding values to bytes.
2
3use crate::config::Config;
4use crate::error::Result;
5
6#[cfg(not(feature = "std"))]
7use alloc::vec::Vec;
8
9/// Writer for encoding values to a byte buffer.
10pub struct Writer {
11    buffer: Vec<u8>,
12    config: Config,
13}
14
15impl Writer {
16    /// Create a new writer with the given configuration.
17    pub fn new(config: Config) -> Self {
18        Self {
19            buffer: Vec::new(),
20            config,
21        }
22    }
23
24    /// Write a single byte.
25    pub fn write_u8(&mut self, value: u8) -> Result<()> {
26        self.buffer.push(value);
27        Ok(())
28    }
29
30    /// Write a u16 in little-endian format.
31    pub fn write_u16(&mut self, value: u16) -> Result<()> {
32        self.buffer.extend_from_slice(&value.to_le_bytes());
33        Ok(())
34    }
35
36    /// Write a u32 in little-endian format.
37    pub fn write_u32(&mut self, value: u32) -> Result<()> {
38        self.buffer.extend_from_slice(&value.to_le_bytes());
39        Ok(())
40    }
41
42    /// Write a u64 in little-endian format.
43    pub fn write_u64(&mut self, value: u64) -> Result<()> {
44        self.buffer.extend_from_slice(&value.to_le_bytes());
45        Ok(())
46    }
47
48    /// Write an i8.
49    pub fn write_i8(&mut self, value: i8) -> Result<()> {
50        self.write_u8(value as u8)
51    }
52
53    /// Write an i16 in little-endian format.
54    pub fn write_i16(&mut self, value: i16) -> Result<()> {
55        self.write_u16(value as u16)
56    }
57
58    /// Write an i32 in little-endian format.
59    pub fn write_i32(&mut self, value: i32) -> Result<()> {
60        self.write_u32(value as u32)
61    }
62
63    /// Write an i64 in little-endian format.
64    pub fn write_i64(&mut self, value: i64) -> Result<()> {
65        self.write_u64(value as u64)
66    }
67
68    /// Write an f32 in little-endian format.
69    pub fn write_f32(&mut self, value: f32) -> Result<()> {
70        self.write_u32(value.to_bits())
71    }
72
73    /// Write an f64 in little-endian format.
74    pub fn write_f64(&mut self, value: f64) -> Result<()> {
75        self.write_u64(value.to_bits())
76    }
77
78    /// Write a boolean (encoded as u8: 0 = false, 1 = true).
79    pub fn write_bool(&mut self, value: bool) -> Result<()> {
80        self.write_u8(if value { 1 } else { 0 })
81    }
82
83    /// Write a byte slice.
84    pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> {
85        self.buffer.extend_from_slice(bytes);
86        Ok(())
87    }
88
89    /// Get the current configuration.
90    pub fn config(&self) -> Config {
91        self.config
92    }
93
94    /// Consume the writer and return the encoded bytes.
95    pub fn into_bytes(self) -> Vec<u8> {
96        self.buffer
97    }
98
99    /// Get a reference to the current buffer.
100    pub fn as_bytes(&self) -> &[u8] {
101        &self.buffer
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use crate::config;
109
110    #[test]
111    fn test_write_primitives() {
112        let config = config::standard();
113        let mut writer = Writer::new(config);
114
115        writer.write_u8(42).unwrap();
116        writer.write_u16(1000).unwrap();
117        writer.write_u32(100000).unwrap();
118        writer.write_u64(1000000000).unwrap();
119        writer.write_bool(true).unwrap();
120        writer.write_bool(false).unwrap();
121
122        let bytes = writer.into_bytes();
123        assert_eq!(bytes.len(), 1 + 2 + 4 + 8 + 1 + 1);
124    }
125
126    #[test]
127    fn test_write_floats() {
128        let config = config::standard();
129        let mut writer = Writer::new(config);
130
131        writer.write_f32(3.14).unwrap();
132        writer.write_f64(2.718).unwrap();
133
134        let bytes = writer.into_bytes();
135        assert_eq!(bytes.len(), 4 + 8);
136    }
137
138    #[test]
139    fn test_write_signed_integers() {
140        let config = config::standard();
141        let mut writer = Writer::new(config);
142
143        writer.write_i8(-42).unwrap();
144        writer.write_i16(-1000).unwrap();
145        writer.write_i32(-100000).unwrap();
146        writer.write_i64(-1000000000).unwrap();
147
148        let bytes = writer.into_bytes();
149        assert_eq!(bytes.len(), 1 + 2 + 4 + 8);
150    }
151
152    #[test]
153    fn test_write_bytes() {
154        let config = config::standard();
155        let mut writer = Writer::new(config);
156        writer.write_bytes(&[1, 2, 3, 4, 5]).unwrap();
157        let bytes = writer.into_bytes();
158        assert_eq!(bytes, &[1, 2, 3, 4, 5]);
159    }
160
161    #[test]
162    fn test_as_bytes() {
163        let config = config::standard();
164        let mut writer = Writer::new(config);
165        writer.write_u8(42).unwrap();
166        let bytes_ref = writer.as_bytes();
167        assert_eq!(bytes_ref, &[42]);
168        // Should still be able to write after as_bytes
169        writer.write_u8(43).unwrap();
170        assert_eq!(writer.as_bytes(), &[42, 43]);
171    }
172
173    #[test]
174    fn test_config() {
175        let config = config::standard().with_limit(100);
176        let writer = Writer::new(config);
177        assert_eq!(writer.config().limit, Some(100));
178    }
179
180    #[test]
181    fn test_write_special_floats() {
182        let config = config::standard();
183        let mut writer = Writer::new(config);
184        
185        writer.write_f32(f32::INFINITY).unwrap();
186        writer.write_f32(f32::NEG_INFINITY).unwrap();
187        writer.write_f32(f32::NAN).unwrap();
188        writer.write_f64(f64::INFINITY).unwrap();
189        writer.write_f64(f64::NEG_INFINITY).unwrap();
190        writer.write_f64(f64::NAN).unwrap();
191        
192        let bytes = writer.into_bytes();
193        assert_eq!(bytes.len(), 4 * 3 + 8 * 3);
194    }
195}
196