Skip to main content

bincake_core/
lib.rs

1mod error;
2mod read_write;
3mod serialize;
4mod serialize_num;
5mod serialize_tuple;
6mod sized_vec;
7
8/// The type used to represent the length of a string when serialized.
9pub type StringSize = u32;
10
11pub use taped::Tape;
12
13// re-export dependency as used in public API
14pub use self::{error::*, read_write::*, serialize::*, sized_vec::*};
15
16#[cfg(test)]
17mod tests {
18    use taped::Tape;
19
20    use crate::{
21        error::{DecodeError, EncodeError},
22        read_write::{Read, Write},
23        serialize::Serialize,
24        sized_vec::{Vec8, Vec16, Vec32},
25        vec8, vec16, vec32, write_all,
26    };
27
28    // Helper function to round-trip test
29    fn round_trip<T: Serialize + PartialEq + std::fmt::Debug>(value: T) {
30        let mut buffer = vec![];
31        buffer.write(&value).expect("Failed to write");
32
33        let mut src = Tape::new(&buffer);
34        let decoded = src.read::<T>().expect("Failed to read");
35
36        dbg!(&src);
37        assert_eq!(value, decoded, "Round-trip failed");
38        assert_eq!(src.rest().len(), 0, "Not all bytes consumed");
39    }
40
41    #[test]
42    fn test_bool_serialization() {
43        round_trip(true);
44        round_trip(false);
45    }
46
47    #[test]
48    fn test_u8_serialization() {
49        round_trip(0u8);
50        round_trip(127u8);
51        round_trip(255u8);
52    }
53
54    #[test]
55    fn test_u16_serialization() {
56        round_trip(0u16);
57        round_trip(256u16);
58        round_trip(u16::MAX);
59    }
60
61    #[test]
62    fn test_u32_serialization() {
63        round_trip(0u32);
64        round_trip(65536u32);
65        round_trip(u32::MAX);
66    }
67
68    #[test]
69    fn test_signed_integers() {
70        round_trip(-128i8);
71        round_trip(127i8);
72        round_trip(-32768i16);
73        round_trip(32767i16);
74        round_trip(i32::MIN);
75        round_trip(i32::MAX);
76        round_trip(i64::MIN);
77        round_trip(i64::MAX);
78        round_trip(i128::MIN);
79        round_trip(i128::MAX);
80    }
81
82    #[test]
83    fn test_floats() {
84        round_trip(0.0f32);
85        round_trip(-0.0f32);
86        round_trip(std::f32::consts::PI);
87        round_trip(f32::INFINITY);
88        round_trip(f32::NEG_INFINITY);
89
90        round_trip(0.0f64);
91        round_trip(std::f64::consts::E);
92        round_trip(f64::INFINITY);
93        round_trip(f64::NEG_INFINITY);
94    }
95
96    #[test]
97    fn test_float_nan() {
98        let mut buffer = vec![];
99        buffer.write(&f32::NAN).unwrap();
100
101        let mut src = Tape::new(&buffer);
102        let decoded = src.read::<f32>().unwrap();
103
104        assert!(decoded.is_nan(), "NaN not preserved");
105    }
106
107    #[test]
108    fn test_string_serialization() {
109        round_trip(String::new());
110        round_trip("hello".to_string());
111        round_trip("Hello, World! 🦀".to_string());
112        round_trip("Multi\nLine\nString".to_string());
113
114        // Long string
115        let long = "a".repeat(1000);
116        round_trip(long);
117    }
118
119    #[test]
120    fn test_string_utf8() {
121        round_trip("日本語".to_string());
122        round_trip("Ñoño español".to_string());
123        round_trip("🎉🎊✨".to_string());
124    }
125
126    #[test]
127    fn test_tuples() {
128        round_trip((42u32, true));
129        round_trip((1u8, 2u16, 3u32));
130        round_trip(("hello".to_string(), 123i32));
131    }
132
133    #[test]
134    fn test_nested_tuples() {
135        round_trip(((1u8, 2u8), (3u8, 4u8)));
136    }
137
138    #[test]
139    fn test_vec8() {
140        let empty: Vec8<u32> = vec8![];
141        round_trip(empty);
142
143        let small = vec8![1u32, 2, 3, 4, 5];
144        round_trip(small);
145
146        // Max size for Vec8
147        let max_vec8 = vec8![0u8; 255];
148        round_trip(max_vec8);
149    }
150
151    #[test]
152    fn test_vec16() {
153        let empty: Vec16<u32> = vec16![];
154        round_trip(empty);
155
156        let medium = vec16![100u32; 300];
157        round_trip(medium);
158    }
159
160    #[test]
161    fn test_vec32() {
162        let empty: Vec32<u32> = vec32![];
163        round_trip(empty);
164
165        let large = vec32![42u32; 10000];
166        round_trip(large);
167    }
168
169    #[test]
170    fn test_vec_of_strings() {
171        let strings = vec32!["hello".to_string(), "world".to_string(), "🦀".to_string(),];
172        round_trip(strings);
173    }
174
175    #[test]
176    fn test_nested_vecs() {
177        let nested = vec32![vec8![1u8, 2, 3], vec8![4, 5], vec8![]];
178        round_trip(nested);
179    }
180
181    #[test]
182    fn test_little_endian_encoding() {
183        // Verify little-endian byte order
184        let mut buffer = vec![];
185        buffer.write(&0x12345678u32).unwrap();
186
187        assert_eq!(buffer, vec![0x78, 0x56, 0x34, 0x12]);
188    }
189
190    #[test]
191    fn test_string_length_prefix() {
192        // Verify string is prefixed with u32 length
193        let mut buffer = vec![];
194        buffer.write(&"abc".to_string()).unwrap();
195
196        // First 4 bytes should be length (3 in little-endian)
197        assert_eq!(buffer[0..4], [3, 0, 0, 0]);
198        // Next 3 bytes should be the string
199        assert_eq!(buffer[4..7], [b'a', b'b', b'c']);
200    }
201
202    #[test]
203    fn test_vec_length_prefix() {
204        let mut buffer = vec![];
205        buffer.write(&vec32![1u8, 2, 3]).unwrap();
206
207        // First 4 bytes should be length (3 in little-endian)
208        assert_eq!(buffer[0..4], [3, 0, 0, 0]);
209        // Next 3 bytes should be the elements
210        assert_eq!(buffer[4..7], [1, 2, 3]);
211    }
212
213    #[test]
214    fn test_empty_buffer_error() {
215        let buffer = vec![];
216        let mut src = Tape::new(&buffer);
217
218        let result = src.read::<u32>();
219        assert!(matches!(result, Err(DecodeError::Exhausted { .. })));
220    }
221
222    #[test]
223    fn test_truncated_data() {
224        let mut buffer = vec![];
225        buffer.write(&42u32).unwrap();
226
227        // Only provide 2 bytes instead of 4
228        let truncated = &buffer[0..2];
229        let mut src = Tape::new(truncated);
230
231        let result = src.read::<u32>();
232        assert!(matches!(result, Err(DecodeError::Exhausted { .. })));
233    }
234
235    #[test]
236    fn test_truncated_string() {
237        let mut buffer = vec![];
238        buffer.write(&"hello".to_string()).unwrap();
239
240        // Truncate the buffer
241        let truncated = &buffer[0..6]; // Length prefix + only 2 chars
242        let mut src = Tape::new(truncated);
243
244        let result = src.read::<String>();
245        assert!(matches!(result, Err(DecodeError::Exhausted { .. })));
246    }
247
248    #[test]
249    fn test_invalid_utf8() {
250        // Manually construct invalid UTF-8 in string format
251        let mut buffer = vec![];
252        // Length: 2
253        buffer.extend_from_slice(&[2, 0, 0, 0]);
254        // Invalid UTF-8 sequence
255        buffer.extend_from_slice(&[0xFF, 0xFE]);
256
257        let mut src = Tape::new(&buffer);
258        let result = src.read::<String>();
259
260        assert!(matches!(result, Err(DecodeError::Other { .. })));
261    }
262
263    #[test]
264    fn test_truncated_vec() {
265        let mut buffer = vec![];
266        buffer.write(&vec32![1u32, 2, 3]).unwrap();
267
268        // Truncate so there's not enough data for all elements
269        let truncated = &buffer[0..8]; // Length prefix + only 1 element
270        let mut src = Tape::new(truncated);
271
272        let result = src.read::<Vec32<u32>>();
273        assert!(matches!(result, Err(DecodeError::Exhausted { .. })));
274    }
275
276    #[test]
277    #[cfg(target_pointer_width = "64")]
278    fn test_array_size_overflow() {
279        // Test that writing a string larger than u32::MAX fails
280        let huge_string = "a".repeat(u32::MAX as usize + 1);
281        let mut buffer = vec![];
282
283        let result = buffer.write(&huge_string);
284        assert!(matches!(
285            result,
286            Err(EncodeError::LengthExceedsPrefix { .. })
287        ));
288    }
289
290    #[test]
291    fn test_byte_stream_operations() {
292        let data = vec![1, 2, 3, 4, 5];
293        let mut src = Tape::new(&data);
294
295        assert_eq!(src.pos, 0);
296        assert_eq!(src.rest().len(), 5);
297
298        assert_eq!(src.next(), Some(1));
299        assert_eq!(src.pos, 1);
300        assert_eq!(src.rest().len(), 4);
301
302        src.pos += 2;
303        assert_eq!(src.pos, 3);
304        assert_eq!(src.rest().len(), 2);
305
306        assert_eq!(src.next(), Some(4));
307        assert_eq!(src.next(), Some(5));
308        assert_eq!(src.next(), None);
309        assert_eq!(src.rest().len(), 0);
310    }
311
312    #[test]
313    fn test_multiple_values_in_sequence() {
314        let mut buffer = vec![];
315
316        // Write multiple values
317        write_all!(buffer;
318            &42u32,
319            &"hello".to_string(),
320            &true,
321            &vec8![1u8, 2, 3],
322        )
323        .unwrap();
324
325        // Read them back
326        let mut src = Tape::new(&buffer);
327
328        let num = src.read::<u32>().unwrap();
329        assert_eq!(num, 42);
330
331        let string = src.read::<String>().unwrap();
332        assert_eq!(string, "hello");
333
334        let boolean = src.read::<bool>().unwrap();
335        assert!(boolean);
336
337        let vec = src.read::<Vec8<u8>>().unwrap();
338        assert_eq!(vec.into_inner(), vec![1, 2, 3]);
339
340        assert_eq!(src.rest().len(), 0);
341    }
342
343    #[test]
344    fn test_complex_structure() {
345        // Simulate a complex structure
346        let mut buffer = vec![];
347
348        // Header
349        buffer.write(&0xCAFEBABEu32).unwrap();
350
351        // Version
352        buffer.write(&(1u16, 0u16)).unwrap();
353
354        // Function table
355        let functions = vec32![("main".to_string(), 0u32), ("helper".to_string(), 100u32),];
356        buffer.write(&functions).unwrap();
357
358        // Constants
359        let constants = vec16!["Hello".to_string(), "World".to_string()];
360        buffer.write(&constants).unwrap();
361
362        // Read it all back
363        let mut src = Tape::new(&buffer);
364
365        let magic = src.read::<u32>().unwrap();
366        assert_eq!(magic, 0xCAFEBABE);
367
368        let version = src.read::<(u16, u16)>().unwrap();
369        assert_eq!(version, (1, 0));
370
371        let funcs = src.read::<Vec32<(String, u32)>>().unwrap();
372        assert_eq!(funcs.len(), 2);
373        assert_eq!(funcs[0].0, "main");
374        assert_eq!(funcs[1].1, 100);
375
376        let consts = src.read::<Vec16<String>>().unwrap();
377        assert_eq!(consts.len(), 2);
378        assert_eq!(consts[0], "Hello");
379
380        assert_eq!(src.rest().len(), 0);
381    }
382
383    #[test]
384    fn test_zero_values() {
385        round_trip(0u8);
386        round_trip(0u16);
387        round_trip(0u32);
388        round_trip(0i8);
389        round_trip(0i16);
390        round_trip(0i32);
391        round_trip(0i64);
392        round_trip(0i128);
393        round_trip(0.0f32);
394        round_trip(0.0f64);
395    }
396
397    #[test]
398    fn test_max_values() {
399        round_trip(u8::MAX);
400        round_trip(u16::MAX);
401        round_trip(u32::MAX);
402        round_trip(i8::MAX);
403        round_trip(i16::MAX);
404        round_trip(i32::MAX);
405        round_trip(i64::MAX);
406        round_trip(i128::MAX);
407    }
408
409    #[test]
410    fn test_min_values() {
411        round_trip(i8::MIN);
412        round_trip(i16::MIN);
413        round_trip(i32::MIN);
414        round_trip(i64::MIN);
415        round_trip(i128::MIN);
416    }
417}