Skip to main content

ax_codec_core/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![deny(unsafe_code)]
3
4#[cfg(feature = "alloc")]
5extern crate alloc;
6
7#[cfg(feature = "alloc")]
8#[doc(hidden)]
9pub use alloc::vec::Vec as __Vec;
10
11pub mod buffer;
12#[cfg(feature = "bytes")]
13pub mod bytes_impl;
14#[cfg(feature = "crc32")]
15pub mod checksum;
16pub mod error;
17pub mod limits;
18pub mod pool;
19#[cfg(feature = "simd")]
20pub mod simd;
21pub mod varint;
22pub mod version;
23
24pub use error::{DecodeError, EncodeError, ValidateError};
25
26pub trait Encode {
27    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError>;
28
29    #[cfg(feature = "alloc")]
30    fn encode_to_vec(&self) -> Result<alloc::vec::Vec<u8>, EncodeError> {
31        let mut writer = buffer::VecWriter::new();
32        self.encode(&mut writer)?;
33        Ok(writer.into_vec())
34    }
35}
36
37pub trait View<'a>: Sized {
38    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError>;
39}
40
41pub trait Decode: Sized {
42    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError>;
43}
44
45pub trait Validate<'a>: Sized {
46    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError>;
47}
48
49impl<'a, T: View<'a>> Validate<'a> for T {
50    #[inline]
51    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
52        T::view(reader)?;
53        Ok(())
54    }
55}
56
57pub trait FixedSize {
58    const SIZE: usize;
59}
60
61macro_rules! impl_primitive {
62    ($ty:ty, $size:expr) => {
63        impl Encode for $ty {
64            #[inline]
65            fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
66                writer.write_all(&self.to_le_bytes())
67            }
68        }
69
70        impl Decode for $ty {
71            #[inline]
72            fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
73                let mut buf = [0u8; $size];
74                reader.read_exact(&mut buf)?;
75                Ok(Self::from_le_bytes(buf))
76            }
77        }
78
79        impl<'a> View<'a> for $ty {
80            #[inline]
81            fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
82                <Self as Decode>::decode(reader)
83            }
84        }
85
86        impl FixedSize for $ty {
87            const SIZE: usize = $size;
88        }
89    };
90}
91
92impl_primitive!(u8, 1);
93impl_primitive!(i8, 1);
94impl_primitive!(u16, 2);
95impl_primitive!(u32, 4);
96impl_primitive!(i16, 2);
97impl_primitive!(i32, 4);
98impl_primitive!(f32, 4);
99impl_primitive!(f64, 8);
100impl_primitive!(u128, 16);
101impl_primitive!(i128, 16);
102
103impl Encode for u64 {
104    #[inline]
105    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
106        varint::encode_uvarint(*self, writer)
107    }
108}
109
110impl Decode for u64 {
111    #[inline]
112    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
113        varint::decode_uvarint(reader)
114    }
115}
116
117impl<'a> View<'a> for u64 {
118    #[inline]
119    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
120        <Self as Decode>::decode(reader)
121    }
122}
123
124impl Encode for i64 {
125    #[inline]
126    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
127        varint::encode_svarint(*self, writer)
128    }
129}
130
131impl Decode for i64 {
132    #[inline]
133    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
134        varint::decode_svarint(reader)
135    }
136}
137
138impl<'a> View<'a> for i64 {
139    #[inline]
140    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
141        <Self as Decode>::decode(reader)
142    }
143}
144
145impl<T: FixedSize + Encode> Encode for &[T] {
146    #[inline]
147    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
148        let count = self.len() as u64;
149        writer.write_all(&count.to_le_bytes())?;
150        for item in *self {
151            item.encode(writer)?;
152        }
153        Ok(())
154    }
155}
156
157#[allow(unsafe_code)]
158impl<'a, T: FixedSize + Decode> View<'a> for &'a [T] {
159    #[inline]
160    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
161        let mut buf = [0u8; 8];
162        reader.read_exact(&mut buf)?;
163        let len = u64::from_le_bytes(buf) as usize;
164
165        let bytes = reader.remaining();
166        // Check for overflow first, before any other checks
167        let byte_len = len
168            .checked_mul(T::SIZE)
169            .ok_or(DecodeError::AllocationLimitExceeded)?;
170
171        // Now check the limit with the safe byte_len value
172        if len > reader.max_slice_len() {
173            return Err(DecodeError::AllocationLimitExceeded);
174        }
175
176        if bytes.len() < byte_len {
177            return Err(DecodeError::UnexpectedEOF);
178        }
179
180        reader.check_alloc(byte_len)?;
181
182        // SAFETY: We verify that the pointer is properly aligned for T
183        let ptr = bytes.as_ptr();
184        let align = core::mem::align_of::<T>();
185        if (ptr as usize) % align != 0 {
186            return Err(DecodeError::UnexpectedEOF);
187        }
188
189        // SAFETY:
190        // - bytes.len() >= byte_len (verified above)
191        // - byte_len is a multiple of T::SIZE (verified by checked_mul)
192        // - ptr is aligned for T (verified above)
193        let ptr = ptr as *const T;
194        let slice = unsafe { core::slice::from_raw_parts(ptr, len) };
195        reader.advance(byte_len)?;
196        Ok(slice)
197    }
198}
199
200impl Encode for bool {
201    #[inline]
202    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
203        writer.write_all(&[*self as u8])
204    }
205}
206
207impl Decode for bool {
208    #[inline]
209    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
210        let mut buf = [0u8; 1];
211        reader.read_exact(&mut buf)?;
212        match buf[0] {
213            0 => Ok(false),
214            1 => Ok(true),
215            _ => Err(DecodeError::InvalidBool),
216        }
217    }
218}
219
220impl<'a> View<'a> for bool {
221    #[inline]
222    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
223        <Self as Decode>::decode(reader)
224    }
225}
226
227impl FixedSize for bool {
228    const SIZE: usize = 1;
229}
230
231impl<T: Encode> Encode for Option<T> {
232    #[inline]
233    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
234        match self {
235            None => 0u8.encode(writer),
236            Some(v) => {
237                1u8.encode(writer)?;
238                v.encode(writer)
239            }
240        }
241    }
242}
243
244impl<T: Decode> Decode for Option<T> {
245    #[inline]
246    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
247        let tag = u8::decode(reader)?;
248        match tag {
249            0 => Ok(None),
250            1 => Ok(Some(T::decode(reader)?)),
251            _ => Err(DecodeError::InvalidOptionTag),
252        }
253    }
254}
255
256impl<'a, T: View<'a>> View<'a> for Option<T> {
257    #[inline]
258    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
259        let tag = u8::decode(reader)?;
260        match tag {
261            0 => Ok(None),
262            1 => Ok(Some(T::view(reader)?)),
263            _ => Err(DecodeError::InvalidOptionTag),
264        }
265    }
266}
267
268pub trait BufferWriter {
269    fn write_all(&mut self, buf: &[u8]) -> Result<(), EncodeError>;
270}
271
272pub trait BufferReader<'a> {
273    fn peek(&self) -> Option<u8>;
274    fn next(&mut self) -> Option<u8>;
275    fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), DecodeError>;
276    fn remaining(&self) -> &'a [u8];
277    fn advance(&mut self, n: usize) -> Result<(), DecodeError>;
278
279    #[inline]
280    fn check_alloc(&mut self, _n: usize) -> Result<(), DecodeError> {
281        Ok(())
282    }
283
284    #[inline]
285    fn depth_enter(&mut self) -> Result<(), DecodeError> {
286        Ok(())
287    }
288
289    #[inline]
290    fn depth_exit(&mut self) {}
291
292    #[inline]
293    fn max_slice_len(&self) -> usize {
294        1024 * 1024 // Default limit
295    }
296
297    #[inline]
298    fn max_string_len(&self) -> usize {
299        16 * 1024 * 1024 // Default limit
300    }
301
302    #[inline]
303    fn max_vec_len(&self) -> usize {
304        1024 * 1024 // Default limit
305    }
306}
307
308#[cfg(feature = "alloc")]
309impl Encode for alloc::string::String {
310    #[inline]
311    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
312        varint::encode_uvarint(self.len() as u64, writer)?;
313        writer.write_all(self.as_bytes())
314    }
315}
316
317#[cfg(feature = "alloc")]
318impl Decode for alloc::string::String {
319    #[inline]
320    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
321        let len = varint::decode_uvarint(reader)? as usize;
322        if len > reader.max_string_len() {
323            return Err(DecodeError::AllocationLimitExceeded);
324        }
325        reader.check_alloc(len)?;
326        let bytes = reader.remaining();
327        if bytes.len() < len {
328            return Err(DecodeError::UnexpectedEOF);
329        }
330        let s = core::str::from_utf8(&bytes[..len]).map_err(|_| DecodeError::InvalidUtf8)?;
331        let owned = alloc::string::String::from(s);
332        reader.advance(len)?;
333        Ok(owned)
334    }
335}
336
337#[cfg(feature = "alloc")]
338impl<'a> Validate<'a> for alloc::string::String {
339    #[inline]
340    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
341        let len =
342            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
343        if len > reader.max_string_len() {
344            return Err(ValidateError::AllocationLimitExceeded);
345        }
346        let bytes = reader.remaining();
347        if bytes.len() < len {
348            return Err(ValidateError::UnexpectedEOF);
349        }
350        core::str::from_utf8(&bytes[..len]).map_err(|_| ValidateError::InvalidUtf8)?;
351        reader
352            .advance(len)
353            .map_err(|_| ValidateError::UnexpectedEOF)?;
354        Ok(())
355    }
356}
357
358impl Encode for &str {
359    #[inline]
360    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
361        varint::encode_uvarint(self.len() as u64, writer)?;
362        writer.write_all(self.as_bytes())
363    }
364}
365
366impl<'a> View<'a> for &'a str {
367    #[inline]
368    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
369        let len = varint::decode_uvarint(reader)? as usize;
370        let bytes = reader.remaining();
371        if bytes.len() < len {
372            return Err(DecodeError::UnexpectedEOF);
373        }
374        let s = core::str::from_utf8(&bytes[..len]).map_err(|_| DecodeError::InvalidUtf8)?;
375        reader.advance(len)?;
376        Ok(s)
377    }
378}
379
380#[cfg(feature = "alloc")]
381impl<T: Decode> Decode for alloc::vec::Vec<T> {
382    #[inline]
383    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
384        let len = varint::decode_uvarint(reader)? as usize;
385        if len > reader.max_vec_len() {
386            return Err(DecodeError::AllocationLimitExceeded);
387        }
388        reader.check_alloc(len)?;
389        let mut vec = alloc::vec::Vec::with_capacity(len);
390        for _ in 0..len {
391            vec.push(T::decode(reader)?);
392        }
393        Ok(vec)
394    }
395}
396
397#[cfg(feature = "alloc")]
398#[inline]
399pub fn decode_vec_u8<'a, R: BufferReader<'a>>(
400    reader: &mut R,
401) -> Result<alloc::vec::Vec<u8>, DecodeError> {
402    let len = varint::decode_uvarint(reader)? as usize;
403    if len > reader.max_vec_len() {
404        return Err(DecodeError::AllocationLimitExceeded);
405    }
406    reader.check_alloc(len)?;
407
408    let bytes = reader.remaining();
409    if bytes.len() < len {
410        return Err(DecodeError::UnexpectedEOF);
411    }
412
413    let mut vec = alloc::vec::Vec::with_capacity(len);
414    vec.extend_from_slice(&bytes[..len]);
415    reader.advance(len)?;
416    Ok(vec)
417}
418
419#[cfg(feature = "alloc")]
420impl<'a, T: Validate<'a>> Validate<'a> for alloc::vec::Vec<T> {
421    #[inline]
422    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
423        let len =
424            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
425        if len > reader.max_vec_len() {
426            return Err(ValidateError::AllocationLimitExceeded);
427        }
428        for _ in 0..len {
429            T::validate(reader)?;
430        }
431        Ok(())
432    }
433}
434
435#[cfg(feature = "alloc")]
436impl<T: Encode> Encode for alloc::vec::Vec<T> {
437    #[inline]
438    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
439        varint::encode_uvarint(self.len() as u64, writer)?;
440        for item in self {
441            item.encode(writer)?;
442        }
443        Ok(())
444    }
445}
446
447#[cfg(feature = "alloc")]
448impl<T: Encode> Encode for alloc::boxed::Box<T> {
449    #[inline]
450    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
451        (**self).encode(writer)
452    }
453}
454
455#[cfg(feature = "alloc")]
456impl<T: Decode> Decode for alloc::boxed::Box<T> {
457    #[inline]
458    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
459        Ok(alloc::boxed::Box::new(T::decode(reader)?))
460    }
461}
462
463#[cfg(feature = "alloc")]
464impl<'a> View<'a> for alloc::borrow::Cow<'a, str> {
465    #[inline]
466    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
467        let len = varint::decode_uvarint(reader)? as usize;
468        let bytes = reader.remaining();
469        if bytes.len() < len {
470            return Err(DecodeError::UnexpectedEOF);
471        }
472        match core::str::from_utf8(&bytes[..len]) {
473            Ok(s) => {
474                reader.advance(len)?;
475                Ok(alloc::borrow::Cow::Borrowed(s))
476            }
477            Err(_) => Err(DecodeError::InvalidUtf8),
478        }
479    }
480}
481
482#[cfg(feature = "alloc")]
483impl<'a> View<'a> for alloc::borrow::Cow<'a, [u8]> {
484    #[inline]
485    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
486        let len = varint::decode_uvarint(reader)? as usize;
487        let bytes = reader.remaining();
488        if bytes.len() < len {
489            return Err(DecodeError::UnexpectedEOF);
490        }
491        let slice = &bytes[..len];
492        reader.advance(len)?;
493        Ok(alloc::borrow::Cow::Borrowed(slice))
494    }
495}
496
497#[cfg(feature = "alloc")]
498impl<'a> Decode for alloc::borrow::Cow<'a, str> {
499    #[inline]
500    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
501        let s = alloc::string::String::decode(reader)?;
502        Ok(alloc::borrow::Cow::Owned(s))
503    }
504}
505
506#[cfg(feature = "alloc")]
507impl<'a> Decode for alloc::borrow::Cow<'a, [u8]> {
508    #[inline]
509    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
510        let v = alloc::vec::Vec::<u8>::decode(reader)?;
511        Ok(alloc::borrow::Cow::Owned(v))
512    }
513}
514
515#[cfg(feature = "alloc")]
516impl<'a> Encode for alloc::borrow::Cow<'a, [u8]> {
517    #[inline]
518    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
519        varint::encode_uvarint(self.len() as u64, writer)?;
520        writer.write_all(self.as_ref())
521    }
522}
523
524#[cfg(feature = "alloc")]
525impl Encode for alloc::borrow::Cow<'_, str> {
526    #[inline]
527    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
528        varint::encode_uvarint(self.len() as u64, writer)?;
529        writer.write_all(self.as_bytes())
530    }
531}
532
533#[cfg(feature = "axhash")]
534impl<K: Encode, V: Encode> Encode for axhash_map::HashMap<K, V> {
535    #[inline]
536    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
537        varint::encode_uvarint(self.len() as u64, writer)?;
538        for (k, v) in self.iter() {
539            k.encode(writer)?;
540            v.encode(writer)?;
541        }
542        Ok(())
543    }
544}
545
546#[cfg(feature = "axhash")]
547impl<K: Decode + Eq + core::hash::Hash, V: Decode> Decode for axhash_map::HashMap<K, V> {
548    #[inline]
549    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
550        let len = varint::decode_uvarint(reader)? as usize;
551        if len > reader.max_vec_len() {
552            return Err(DecodeError::AllocationLimitExceeded);
553        }
554        let mut map = axhash_map::HashMap::default();
555        map.reserve(len);
556        for _ in 0..len {
557            let k = K::decode(reader)?;
558            let v = V::decode(reader)?;
559            map.insert(k, v);
560        }
561        Ok(map)
562    }
563}
564
565#[cfg(feature = "axhash")]
566impl<'a, K: Validate<'a>, V: Validate<'a>> Validate<'a> for axhash_map::HashMap<K, V> {
567    #[inline]
568    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
569        let len =
570            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
571        if len > reader.max_vec_len() {
572            return Err(ValidateError::AllocationLimitExceeded);
573        }
574        for _ in 0..len {
575            K::validate(reader)?;
576            V::validate(reader)?;
577        }
578        Ok(())
579    }
580}
581
582#[cfg(feature = "axhash")]
583impl<T: Encode> Encode for axhash_map::HashSet<T> {
584    #[inline]
585    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
586        varint::encode_uvarint(self.len() as u64, writer)?;
587        for item in self.iter() {
588            item.encode(writer)?;
589        }
590        Ok(())
591    }
592}
593
594#[cfg(feature = "axhash")]
595impl<T: Decode + Eq + core::hash::Hash> Decode for axhash_map::HashSet<T> {
596    #[inline]
597    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
598        let len = varint::decode_uvarint(reader)? as usize;
599        if len > reader.max_vec_len() {
600            return Err(DecodeError::AllocationLimitExceeded);
601        }
602        let mut set = axhash_map::HashSet::default();
603        set.reserve(len);
604        for _ in 0..len {
605            set.insert(T::decode(reader)?);
606        }
607        Ok(set)
608    }
609}
610
611#[cfg(feature = "axhash")]
612impl<'a, T: Validate<'a>> Validate<'a> for axhash_map::HashSet<T> {
613    #[inline]
614    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
615        let len =
616            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
617        if len > reader.max_vec_len() {
618            return Err(ValidateError::AllocationLimitExceeded);
619        }
620        for _ in 0..len {
621            T::validate(reader)?;
622        }
623        Ok(())
624    }
625}
626
627#[cfg(test)]
628mod tests {
629    use super::*;
630    use crate::Validate;
631
632    #[test]
633    fn roundtrip_u16() {
634        let mut w = buffer::VecWriter::new();
635        let val: u16 = 0x1234;
636        val.encode(&mut w).unwrap();
637        let mut r = buffer::SliceReader::new(w.as_slice());
638        let decoded = u16::decode(&mut r).unwrap();
639        assert_eq!(val, decoded);
640    }
641
642    #[test]
643    fn roundtrip_option_some() {
644        let mut w = buffer::VecWriter::new();
645        let val: Option<u16> = Some(0x1234);
646        val.encode(&mut w).unwrap();
647        let mut r = buffer::SliceReader::new(w.as_slice());
648        let decoded = Option::<u16>::decode(&mut r).unwrap();
649        assert_eq!(val, decoded);
650    }
651
652    #[test]
653    fn roundtrip_option_none() {
654        let mut w = buffer::VecWriter::new();
655        let val: Option<u16> = None;
656        val.encode(&mut w).unwrap();
657        let mut r = buffer::SliceReader::new(w.as_slice());
658        let decoded = Option::<u16>::decode(&mut r).unwrap();
659        assert_eq!(val, decoded);
660    }
661
662    #[test]
663    fn validate_u16_ok() {
664        let mut w = buffer::VecWriter::new();
665        let val: u16 = 0x1234;
666        val.encode(&mut w).unwrap();
667        let mut r = buffer::SliceReader::new(w.as_slice());
668        u16::validate(&mut r).unwrap();
669    }
670
671    #[test]
672    fn validate_u16_eof_fails() {
673        let buf = [0x12u8]; // only 1 byte for u16
674        let mut r = buffer::SliceReader::new(&buf);
675        assert!(u16::validate(&mut r).is_err());
676    }
677
678    #[test]
679    fn validate_bool_ok() {
680        let mut w = buffer::VecWriter::new();
681        true.encode(&mut w).unwrap();
682        let mut r = buffer::SliceReader::new(w.as_slice());
683        bool::validate(&mut r).unwrap();
684    }
685
686    #[test]
687    fn validate_bool_invalid_fails() {
688        let buf = [0x02u8];
689        let mut r = buffer::SliceReader::new(&buf);
690        assert!(bool::validate(&mut r).is_err());
691    }
692
693    #[test]
694    #[cfg(feature = "axhash")]
695    fn hashmap_roundtrip() {
696        use axhash_map::HashMap;
697        let mut map: HashMap<String, u32> = HashMap::default();
698        map.insert("alice".into(), 42u32);
699        map.insert("bob".into(), 17u32);
700
701        let mut w = buffer::VecWriter::new();
702        map.encode(&mut w).unwrap();
703
704        let mut r = buffer::SliceReader::new(w.as_slice());
705        let decoded = HashMap::<String, u32>::decode(&mut r).unwrap();
706
707        assert_eq!(decoded.len(), 2);
708        assert_eq!(decoded["alice"], 42);
709        assert_eq!(decoded["bob"], 17);
710    }
711
712    #[test]
713    #[cfg(feature = "axhash")]
714    fn hashset_roundtrip() {
715        use axhash_map::HashSet;
716        let mut set: HashSet<u32> = HashSet::default();
717        set.insert(1u32);
718        set.insert(2u32);
719        set.insert(3u32);
720
721        let mut w = buffer::VecWriter::new();
722        set.encode(&mut w).unwrap();
723
724        let mut r = buffer::SliceReader::new(w.as_slice());
725        let decoded = HashSet::<u32>::decode(&mut r).unwrap();
726
727        assert_eq!(decoded.len(), 3);
728        assert!(decoded.contains(&1));
729        assert!(decoded.contains(&2));
730        assert!(decoded.contains(&3));
731    }
732
733    #[test]
734    #[cfg(feature = "axhash")]
735    fn hashmap_validate_ok() {
736        use axhash_map::HashMap;
737        let mut map: HashMap<String, u32> = HashMap::default();
738        map.insert("alice".into(), 42u32);
739
740        let mut w = buffer::VecWriter::new();
741        map.encode(&mut w).unwrap();
742
743        let mut r = buffer::SliceReader::new(w.as_slice());
744        HashMap::<String, u32>::validate(&mut r).unwrap();
745    }
746
747    #[test]
748    #[cfg(feature = "axhash")]
749    fn hashset_validate_ok() {
750        use axhash_map::HashSet;
751        let mut set: HashSet<u32> = HashSet::default();
752        set.insert(1u32);
753
754        let mut w = buffer::VecWriter::new();
755        set.encode(&mut w).unwrap();
756
757        let mut r = buffer::SliceReader::new(w.as_slice());
758        HashSet::<u32>::validate(&mut r).unwrap();
759    }
760
761    #[test]
762    #[cfg(feature = "crc32")]
763    fn checksum_roundtrip_u16() {
764        let val: u16 = 0x1234;
765        let mut w = buffer::VecWriter::new();
766        checksum::encode_with_checksum(&val, &mut w).unwrap();
767
768        let mut r = buffer::SliceReader::new(w.as_slice());
769        let decoded = checksum::decode_with_checksum::<u16, _>(&mut r).unwrap();
770        assert_eq!(val, decoded);
771    }
772
773    #[test]
774    #[cfg(feature = "crc32")]
775    fn checksum_corrupted_fails() {
776        let val: u16 = 0x1234;
777        let mut w = buffer::VecWriter::new();
778        checksum::encode_with_checksum(&val, &mut w).unwrap();
779
780        let mut bytes = w.into_vec();
781        bytes[0] ^= 0xFF; // corrupt first byte
782
783        let mut r = buffer::SliceReader::new(&bytes);
784        assert!(checksum::decode_with_checksum::<u16, _>(&mut r).is_err());
785    }
786
787    #[test]
788    #[cfg(feature = "crc32")]
789    fn checksum_validate_ok() {
790        let val: u16 = 0x1234;
791        let mut w = buffer::VecWriter::new();
792        checksum::encode_with_checksum(&val, &mut w).unwrap();
793
794        let mut r = buffer::SliceReader::new(w.as_slice());
795        checksum::validate_with_checksum::<u16, _>(&mut r).unwrap();
796    }
797
798    #[test]
799    fn versioned_roundtrip() {
800        let val: u16 = 0x1234;
801        let mut w = buffer::VecWriter::new();
802        version::encode_versioned(1, &val, &mut w).unwrap();
803
804        let mut r = buffer::SliceReader::new(w.as_slice());
805        let (ver, decoded) = version::decode_versioned::<u16, _>(0, 2, &mut r).unwrap();
806        assert_eq!(ver, 1);
807        assert_eq!(decoded, val);
808    }
809
810    #[test]
811    fn versioned_out_of_range_fails() {
812        let val: u16 = 0x1234;
813        let mut w = buffer::VecWriter::new();
814        version::encode_versioned(5, &val, &mut w).unwrap();
815
816        let mut r = buffer::SliceReader::new(w.as_slice());
817        assert!(version::decode_versioned::<u16, _>(0, 2, &mut r).is_err());
818    }
819
820    #[test]
821    fn zero_copy_slice_u32() {
822        let vals = [0x01020304u32, 0x05060708, 0x090a0b0c];
823        let mut w = buffer::VecWriter::new();
824        w.write_all(&(vals.len() as u64).to_le_bytes()).unwrap();
825        for v in &vals {
826            v.encode(&mut w).unwrap();
827        }
828
829        let mut r = buffer::SliceReader::new(w.as_slice());
830        let slice: &[u32] = View::view(&mut r).unwrap();
831        assert_eq!(slice, &vals);
832    }
833
834    #[test]
835    fn zero_copy_slice_u16() {
836        let vals = [0x1234u16, 0x5678];
837        let mut w = buffer::VecWriter::new();
838        w.write_all(&(vals.len() as u64).to_le_bytes()).unwrap();
839        for v in &vals {
840            v.encode(&mut w).unwrap();
841        }
842
843        let mut r = buffer::SliceReader::new(w.as_slice());
844        let slice: &[u16] = View::view(&mut r).unwrap();
845        assert_eq!(slice, &vals);
846    }
847
848    #[test]
849    #[cfg(feature = "bytes")]
850    fn bytes_decode_u16_roundtrip() {
851        let val: u16 = 0x1234;
852        let mut w = buffer::VecWriter::new();
853        val.encode(&mut w).unwrap();
854
855        let mut buf = bytes::Bytes::copy_from_slice(w.as_slice());
856        let decoded = bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap();
857        assert_eq!(val, decoded);
858    }
859
860    #[test]
861    fn decode_vec_u8_bulk_copy() {
862        let data = alloc::vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
863        let mut w = buffer::VecWriter::new();
864        data.encode(&mut w).unwrap();
865
866        let mut r = buffer::SliceReader::new(w.as_slice());
867        let decoded = decode_vec_u8(&mut r).unwrap();
868        assert_eq!(decoded, data);
869    }
870
871    #[test]
872    #[cfg(feature = "bytes")]
873    fn bytes_decode_multiple_values() {
874        let mut w = buffer::VecWriter::new();
875        0x0102u16.encode(&mut w).unwrap();
876        0x0304u16.encode(&mut w).unwrap();
877        0x0506u16.encode(&mut w).unwrap();
878
879        let mut buf = bytes::Bytes::copy_from_slice(w.as_slice());
880        assert_eq!(
881            bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap(),
882            0x0102
883        );
884        assert_eq!(
885            bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap(),
886            0x0304
887        );
888        assert_eq!(
889            bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap(),
890            0x0506
891        );
892    }
893}