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        if len > 1024 * 1024 {
165            return Err(DecodeError::AllocationLimitExceeded);
166        }
167        reader.check_alloc(len * T::SIZE)?;
168
169        let bytes = reader.remaining();
170        let byte_len = len
171            .checked_mul(T::SIZE)
172            .ok_or(DecodeError::AllocationLimitExceeded)?;
173        if bytes.len() < byte_len {
174            return Err(DecodeError::UnexpectedEOF);
175        }
176
177        // SAFETY: We've verified that bytes.len() >= byte_len and byte_len is a multiple of T::SIZE
178        // We've also verified alignment by checking that T::SIZE is a power of two in the FixedSize trait
179        // (or we should add that constraint)
180        let ptr = bytes.as_ptr() as *const T;
181        let slice = unsafe { core::slice::from_raw_parts(ptr, len) };
182        reader.advance(byte_len)?;
183        Ok(slice)
184    }
185}
186
187impl Encode for bool {
188    #[inline]
189    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
190        writer.write_all(&[*self as u8])
191    }
192}
193
194impl Decode for bool {
195    #[inline]
196    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
197        let mut buf = [0u8; 1];
198        reader.read_exact(&mut buf)?;
199        match buf[0] {
200            0 => Ok(false),
201            1 => Ok(true),
202            _ => Err(DecodeError::InvalidBool),
203        }
204    }
205}
206
207impl<'a> View<'a> for bool {
208    #[inline]
209    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
210        <Self as Decode>::decode(reader)
211    }
212}
213
214impl FixedSize for bool {
215    const SIZE: usize = 1;
216}
217
218impl<T: Encode> Encode for Option<T> {
219    #[inline]
220    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
221        match self {
222            None => 0u8.encode(writer),
223            Some(v) => {
224                1u8.encode(writer)?;
225                v.encode(writer)
226            }
227        }
228    }
229}
230
231impl<T: Decode> Decode for Option<T> {
232    #[inline]
233    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
234        let tag = u8::decode(reader)?;
235        match tag {
236            0 => Ok(None),
237            1 => Ok(Some(T::decode(reader)?)),
238            _ => Err(DecodeError::InvalidOptionTag),
239        }
240    }
241}
242
243impl<'a, T: View<'a>> View<'a> for Option<T> {
244    #[inline]
245    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
246        let tag = u8::decode(reader)?;
247        match tag {
248            0 => Ok(None),
249            1 => Ok(Some(T::view(reader)?)),
250            _ => Err(DecodeError::InvalidOptionTag),
251        }
252    }
253}
254
255pub trait BufferWriter {
256    fn write_all(&mut self, buf: &[u8]) -> Result<(), EncodeError>;
257}
258
259pub trait BufferReader<'a> {
260    fn peek(&self) -> Option<u8>;
261    fn next(&mut self) -> Option<u8>;
262    fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), DecodeError>;
263    fn remaining(&self) -> &'a [u8];
264    fn advance(&mut self, n: usize) -> Result<(), DecodeError>;
265
266    #[inline]
267    fn check_alloc(&mut self, _n: usize) -> Result<(), DecodeError> {
268        Ok(())
269    }
270
271    #[inline]
272    fn depth_enter(&mut self) -> Result<(), DecodeError> {
273        Ok(())
274    }
275
276    #[inline]
277    fn depth_exit(&mut self) {}
278}
279
280#[cfg(feature = "alloc")]
281impl Encode for alloc::string::String {
282    #[inline]
283    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
284        varint::encode_uvarint(self.len() as u64, writer)?;
285        writer.write_all(self.as_bytes())
286    }
287}
288
289#[cfg(feature = "alloc")]
290impl Decode for alloc::string::String {
291    #[inline]
292    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
293        let len = varint::decode_uvarint(reader)? as usize;
294        if len > 16 * 1024 * 1024 {
295            return Err(DecodeError::AllocationLimitExceeded);
296        }
297        reader.check_alloc(len)?;
298        let bytes = reader.remaining();
299        if bytes.len() < len {
300            return Err(DecodeError::UnexpectedEOF);
301        }
302        let s = core::str::from_utf8(&bytes[..len]).map_err(|_| DecodeError::InvalidUtf8)?;
303        let owned = alloc::string::String::from(s);
304        reader.advance(len)?;
305        Ok(owned)
306    }
307}
308
309#[cfg(feature = "alloc")]
310impl<'a> Validate<'a> for alloc::string::String {
311    #[inline]
312    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
313        let len =
314            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
315        if len > 16 * 1024 * 1024 {
316            return Err(ValidateError::AllocationLimitExceeded);
317        }
318        let bytes = reader.remaining();
319        if bytes.len() < len {
320            return Err(ValidateError::UnexpectedEOF);
321        }
322        core::str::from_utf8(&bytes[..len]).map_err(|_| ValidateError::InvalidUtf8)?;
323        reader
324            .advance(len)
325            .map_err(|_| ValidateError::UnexpectedEOF)?;
326        Ok(())
327    }
328}
329
330impl Encode for &str {
331    #[inline]
332    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
333        varint::encode_uvarint(self.len() as u64, writer)?;
334        writer.write_all(self.as_bytes())
335    }
336}
337
338impl<'a> View<'a> for &'a str {
339    #[inline]
340    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
341        let len = varint::decode_uvarint(reader)? as usize;
342        let bytes = reader.remaining();
343        if bytes.len() < len {
344            return Err(DecodeError::UnexpectedEOF);
345        }
346        let s = core::str::from_utf8(&bytes[..len]).map_err(|_| DecodeError::InvalidUtf8)?;
347        reader.advance(len)?;
348        Ok(s)
349    }
350}
351
352#[cfg(feature = "alloc")]
353impl<T: Decode> Decode for alloc::vec::Vec<T> {
354    #[inline]
355    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
356        let len = varint::decode_uvarint(reader)? as usize;
357        if len > 1024 * 1024 {
358            return Err(DecodeError::AllocationLimitExceeded);
359        }
360        reader.check_alloc(len)?;
361        let mut vec = alloc::vec::Vec::with_capacity(len);
362        for _ in 0..len {
363            vec.push(T::decode(reader)?);
364        }
365        Ok(vec)
366    }
367}
368
369#[cfg(feature = "alloc")]
370#[inline]
371pub fn decode_vec_u8<'a, R: BufferReader<'a>>(
372    reader: &mut R,
373) -> Result<alloc::vec::Vec<u8>, DecodeError> {
374    let len = varint::decode_uvarint(reader)? as usize;
375    if len > 1024 * 1024 {
376        return Err(DecodeError::AllocationLimitExceeded);
377    }
378    reader.check_alloc(len)?;
379
380    let bytes = reader.remaining();
381    if bytes.len() < len {
382        return Err(DecodeError::UnexpectedEOF);
383    }
384
385    let mut vec = alloc::vec::Vec::with_capacity(len);
386    vec.extend_from_slice(&bytes[..len]);
387    reader.advance(len)?;
388    Ok(vec)
389}
390
391#[cfg(feature = "alloc")]
392impl<'a, T: Validate<'a>> Validate<'a> for alloc::vec::Vec<T> {
393    #[inline]
394    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
395        let len =
396            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
397        if len > 1024 * 1024 {
398            return Err(ValidateError::AllocationLimitExceeded);
399        }
400        for _ in 0..len {
401            T::validate(reader)?;
402        }
403        Ok(())
404    }
405}
406
407#[cfg(feature = "alloc")]
408impl<T: Encode> Encode for alloc::vec::Vec<T> {
409    #[inline]
410    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
411        varint::encode_uvarint(self.len() as u64, writer)?;
412        for item in self {
413            item.encode(writer)?;
414        }
415        Ok(())
416    }
417}
418
419#[cfg(feature = "alloc")]
420impl<T: Encode> Encode for alloc::boxed::Box<T> {
421    #[inline]
422    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
423        (**self).encode(writer)
424    }
425}
426
427#[cfg(feature = "alloc")]
428impl<T: Decode> Decode for alloc::boxed::Box<T> {
429    #[inline]
430    fn decode<'a, R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
431        Ok(alloc::boxed::Box::new(T::decode(reader)?))
432    }
433}
434
435#[cfg(feature = "alloc")]
436impl<'a> View<'a> for alloc::borrow::Cow<'a, str> {
437    #[inline]
438    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
439        let len = varint::decode_uvarint(reader)? as usize;
440        let bytes = reader.remaining();
441        if bytes.len() < len {
442            return Err(DecodeError::UnexpectedEOF);
443        }
444        match core::str::from_utf8(&bytes[..len]) {
445            Ok(s) => {
446                reader.advance(len)?;
447                Ok(alloc::borrow::Cow::Borrowed(s))
448            }
449            Err(_) => Err(DecodeError::InvalidUtf8),
450        }
451    }
452}
453
454#[cfg(feature = "alloc")]
455impl<'a> View<'a> for alloc::borrow::Cow<'a, [u8]> {
456    #[inline]
457    fn view<R: BufferReader<'a>>(reader: &mut R) -> Result<Self, DecodeError> {
458        let len = varint::decode_uvarint(reader)? as usize;
459        let bytes = reader.remaining();
460        if bytes.len() < len {
461            return Err(DecodeError::UnexpectedEOF);
462        }
463        let slice = &bytes[..len];
464        reader.advance(len)?;
465        Ok(alloc::borrow::Cow::Borrowed(slice))
466    }
467}
468
469#[cfg(feature = "alloc")]
470impl<'a> Decode for alloc::borrow::Cow<'a, str> {
471    #[inline]
472    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
473        let s = alloc::string::String::decode(reader)?;
474        Ok(alloc::borrow::Cow::Owned(s))
475    }
476}
477
478#[cfg(feature = "alloc")]
479impl<'a> Decode for alloc::borrow::Cow<'a, [u8]> {
480    #[inline]
481    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
482        let v = alloc::vec::Vec::<u8>::decode(reader)?;
483        Ok(alloc::borrow::Cow::Owned(v))
484    }
485}
486
487#[cfg(feature = "alloc")]
488impl<'a> Encode for alloc::borrow::Cow<'a, [u8]> {
489    #[inline]
490    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
491        varint::encode_uvarint(self.len() as u64, writer)?;
492        writer.write_all(self.as_ref())
493    }
494}
495
496#[cfg(feature = "alloc")]
497impl Encode for alloc::borrow::Cow<'_, str> {
498    #[inline]
499    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
500        varint::encode_uvarint(self.len() as u64, writer)?;
501        writer.write_all(self.as_bytes())
502    }
503}
504
505#[cfg(feature = "axhash")]
506impl<K: Encode, V: Encode> Encode for axhash_map::HashMap<K, V> {
507    #[inline]
508    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
509        varint::encode_uvarint(self.len() as u64, writer)?;
510        for (k, v) in self.iter() {
511            k.encode(writer)?;
512            v.encode(writer)?;
513        }
514        Ok(())
515    }
516}
517
518#[cfg(feature = "axhash")]
519impl<K: Decode + Eq + core::hash::Hash, V: Decode> Decode for axhash_map::HashMap<K, V> {
520    #[inline]
521    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
522        let len = varint::decode_uvarint(reader)? as usize;
523        if len > 1024 * 1024 {
524            return Err(DecodeError::AllocationLimitExceeded);
525        }
526        let mut map = axhash_map::HashMap::default();
527        map.reserve(len);
528        for _ in 0..len {
529            let k = K::decode(reader)?;
530            let v = V::decode(reader)?;
531            map.insert(k, v);
532        }
533        Ok(map)
534    }
535}
536
537#[cfg(feature = "axhash")]
538impl<'a, K: Validate<'a>, V: Validate<'a>> Validate<'a> for axhash_map::HashMap<K, V> {
539    #[inline]
540    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
541        let len =
542            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
543        if len > 1024 * 1024 {
544            return Err(ValidateError::AllocationLimitExceeded);
545        }
546        for _ in 0..len {
547            K::validate(reader)?;
548            V::validate(reader)?;
549        }
550        Ok(())
551    }
552}
553
554#[cfg(feature = "axhash")]
555impl<T: Encode> Encode for axhash_map::HashSet<T> {
556    #[inline]
557    fn encode<W: BufferWriter>(&self, writer: &mut W) -> Result<(), EncodeError> {
558        varint::encode_uvarint(self.len() as u64, writer)?;
559        for item in self.iter() {
560            item.encode(writer)?;
561        }
562        Ok(())
563    }
564}
565
566#[cfg(feature = "axhash")]
567impl<T: Decode + Eq + core::hash::Hash> Decode for axhash_map::HashSet<T> {
568    #[inline]
569    fn decode<'__b, R: BufferReader<'__b>>(reader: &mut R) -> Result<Self, DecodeError> {
570        let len = varint::decode_uvarint(reader)? as usize;
571        if len > 1024 * 1024 {
572            return Err(DecodeError::AllocationLimitExceeded);
573        }
574        let mut set = axhash_map::HashSet::default();
575        set.reserve(len);
576        for _ in 0..len {
577            set.insert(T::decode(reader)?);
578        }
579        Ok(set)
580    }
581}
582
583#[cfg(feature = "axhash")]
584impl<'a, T: Validate<'a>> Validate<'a> for axhash_map::HashSet<T> {
585    #[inline]
586    fn validate<R: BufferReader<'a>>(reader: &mut R) -> Result<(), ValidateError> {
587        let len =
588            varint::decode_uvarint(reader).map_err(|_| ValidateError::InvalidVarint)? as usize;
589        if len > 1024 * 1024 {
590            return Err(ValidateError::AllocationLimitExceeded);
591        }
592        for _ in 0..len {
593            T::validate(reader)?;
594        }
595        Ok(())
596    }
597}
598
599#[cfg(test)]
600mod tests {
601    use super::*;
602    use crate::Validate;
603
604    #[test]
605    fn roundtrip_u16() {
606        let mut w = buffer::VecWriter::new();
607        let val: u16 = 0x1234;
608        val.encode(&mut w).unwrap();
609        let mut r = buffer::SliceReader::new(w.as_slice());
610        let decoded = u16::decode(&mut r).unwrap();
611        assert_eq!(val, decoded);
612    }
613
614    #[test]
615    fn roundtrip_option_some() {
616        let mut w = buffer::VecWriter::new();
617        let val: Option<u16> = Some(0x1234);
618        val.encode(&mut w).unwrap();
619        let mut r = buffer::SliceReader::new(w.as_slice());
620        let decoded = Option::<u16>::decode(&mut r).unwrap();
621        assert_eq!(val, decoded);
622    }
623
624    #[test]
625    fn roundtrip_option_none() {
626        let mut w = buffer::VecWriter::new();
627        let val: Option<u16> = None;
628        val.encode(&mut w).unwrap();
629        let mut r = buffer::SliceReader::new(w.as_slice());
630        let decoded = Option::<u16>::decode(&mut r).unwrap();
631        assert_eq!(val, decoded);
632    }
633
634    #[test]
635    fn validate_u16_ok() {
636        let mut w = buffer::VecWriter::new();
637        let val: u16 = 0x1234;
638        val.encode(&mut w).unwrap();
639        let mut r = buffer::SliceReader::new(w.as_slice());
640        u16::validate(&mut r).unwrap();
641    }
642
643    #[test]
644    fn validate_u16_eof_fails() {
645        let buf = [0x12u8]; // only 1 byte for u16
646        let mut r = buffer::SliceReader::new(&buf);
647        assert!(u16::validate(&mut r).is_err());
648    }
649
650    #[test]
651    fn validate_bool_ok() {
652        let mut w = buffer::VecWriter::new();
653        true.encode(&mut w).unwrap();
654        let mut r = buffer::SliceReader::new(w.as_slice());
655        bool::validate(&mut r).unwrap();
656    }
657
658    #[test]
659    fn validate_bool_invalid_fails() {
660        let buf = [0x02u8];
661        let mut r = buffer::SliceReader::new(&buf);
662        assert!(bool::validate(&mut r).is_err());
663    }
664
665    #[test]
666    #[cfg(feature = "axhash")]
667    fn hashmap_roundtrip() {
668        use axhash_map::HashMap;
669        let mut map: HashMap<String, u32> = HashMap::default();
670        map.insert("alice".into(), 42u32);
671        map.insert("bob".into(), 17u32);
672
673        let mut w = buffer::VecWriter::new();
674        map.encode(&mut w).unwrap();
675
676        let mut r = buffer::SliceReader::new(w.as_slice());
677        let decoded = HashMap::<String, u32>::decode(&mut r).unwrap();
678
679        assert_eq!(decoded.len(), 2);
680        assert_eq!(decoded["alice"], 42);
681        assert_eq!(decoded["bob"], 17);
682    }
683
684    #[test]
685    #[cfg(feature = "axhash")]
686    fn hashset_roundtrip() {
687        use axhash_map::HashSet;
688        let mut set: HashSet<u32> = HashSet::default();
689        set.insert(1u32);
690        set.insert(2u32);
691        set.insert(3u32);
692
693        let mut w = buffer::VecWriter::new();
694        set.encode(&mut w).unwrap();
695
696        let mut r = buffer::SliceReader::new(w.as_slice());
697        let decoded = HashSet::<u32>::decode(&mut r).unwrap();
698
699        assert_eq!(decoded.len(), 3);
700        assert!(decoded.contains(&1));
701        assert!(decoded.contains(&2));
702        assert!(decoded.contains(&3));
703    }
704
705    #[test]
706    #[cfg(feature = "axhash")]
707    fn hashmap_validate_ok() {
708        use axhash_map::HashMap;
709        let mut map: HashMap<String, u32> = HashMap::default();
710        map.insert("alice".into(), 42u32);
711
712        let mut w = buffer::VecWriter::new();
713        map.encode(&mut w).unwrap();
714
715        let mut r = buffer::SliceReader::new(w.as_slice());
716        HashMap::<String, u32>::validate(&mut r).unwrap();
717    }
718
719    #[test]
720    #[cfg(feature = "axhash")]
721    fn hashset_validate_ok() {
722        use axhash_map::HashSet;
723        let mut set: HashSet<u32> = HashSet::default();
724        set.insert(1u32);
725
726        let mut w = buffer::VecWriter::new();
727        set.encode(&mut w).unwrap();
728
729        let mut r = buffer::SliceReader::new(w.as_slice());
730        HashSet::<u32>::validate(&mut r).unwrap();
731    }
732
733    #[test]
734    #[cfg(feature = "crc32")]
735    fn checksum_roundtrip_u16() {
736        let val: u16 = 0x1234;
737        let mut w = buffer::VecWriter::new();
738        checksum::encode_with_checksum(&val, &mut w).unwrap();
739
740        let mut r = buffer::SliceReader::new(w.as_slice());
741        let decoded = checksum::decode_with_checksum::<u16, _>(&mut r).unwrap();
742        assert_eq!(val, decoded);
743    }
744
745    #[test]
746    #[cfg(feature = "crc32")]
747    fn checksum_corrupted_fails() {
748        let val: u16 = 0x1234;
749        let mut w = buffer::VecWriter::new();
750        checksum::encode_with_checksum(&val, &mut w).unwrap();
751
752        let mut bytes = w.into_vec();
753        bytes[0] ^= 0xFF; // corrupt first byte
754
755        let mut r = buffer::SliceReader::new(&bytes);
756        assert!(checksum::decode_with_checksum::<u16, _>(&mut r).is_err());
757    }
758
759    #[test]
760    #[cfg(feature = "crc32")]
761    fn checksum_validate_ok() {
762        let val: u16 = 0x1234;
763        let mut w = buffer::VecWriter::new();
764        checksum::encode_with_checksum(&val, &mut w).unwrap();
765
766        let mut r = buffer::SliceReader::new(w.as_slice());
767        checksum::validate_with_checksum::<u16, _>(&mut r).unwrap();
768    }
769
770    #[test]
771    fn versioned_roundtrip() {
772        let val: u16 = 0x1234;
773        let mut w = buffer::VecWriter::new();
774        version::encode_versioned(1, &val, &mut w).unwrap();
775
776        let mut r = buffer::SliceReader::new(w.as_slice());
777        let (ver, decoded) = version::decode_versioned::<u16, _>(0, 2, &mut r).unwrap();
778        assert_eq!(ver, 1);
779        assert_eq!(decoded, val);
780    }
781
782    #[test]
783    fn versioned_out_of_range_fails() {
784        let val: u16 = 0x1234;
785        let mut w = buffer::VecWriter::new();
786        version::encode_versioned(5, &val, &mut w).unwrap();
787
788        let mut r = buffer::SliceReader::new(w.as_slice());
789        assert!(version::decode_versioned::<u16, _>(0, 2, &mut r).is_err());
790    }
791
792    #[test]
793    fn zero_copy_slice_u32() {
794        let vals = [0x01020304u32, 0x05060708, 0x090a0b0c];
795        let mut w = buffer::VecWriter::new();
796        w.write_all(&(vals.len() as u64).to_le_bytes()).unwrap();
797        for v in &vals {
798            v.encode(&mut w).unwrap();
799        }
800
801        let mut r = buffer::SliceReader::new(w.as_slice());
802        let slice: &[u32] = View::view(&mut r).unwrap();
803        assert_eq!(slice, &vals);
804    }
805
806    #[test]
807    fn zero_copy_slice_u16() {
808        let vals = [0x1234u16, 0x5678];
809        let mut w = buffer::VecWriter::new();
810        w.write_all(&(vals.len() as u64).to_le_bytes()).unwrap();
811        for v in &vals {
812            v.encode(&mut w).unwrap();
813        }
814
815        let mut r = buffer::SliceReader::new(w.as_slice());
816        let slice: &[u16] = View::view(&mut r).unwrap();
817        assert_eq!(slice, &vals);
818    }
819
820    #[test]
821    #[cfg(feature = "bytes")]
822    fn bytes_decode_u16_roundtrip() {
823        let val: u16 = 0x1234;
824        let mut w = buffer::VecWriter::new();
825        val.encode(&mut w).unwrap();
826
827        let mut buf = bytes::Bytes::copy_from_slice(w.as_slice());
828        let decoded = bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap();
829        assert_eq!(val, decoded);
830    }
831
832    #[test]
833    fn decode_vec_u8_bulk_copy() {
834        let data = alloc::vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
835        let mut w = buffer::VecWriter::new();
836        data.encode(&mut w).unwrap();
837
838        let mut r = buffer::SliceReader::new(w.as_slice());
839        let decoded = decode_vec_u8(&mut r).unwrap();
840        assert_eq!(decoded, data);
841    }
842
843    #[test]
844    #[cfg(feature = "bytes")]
845    fn bytes_decode_multiple_values() {
846        let mut w = buffer::VecWriter::new();
847        0x0102u16.encode(&mut w).unwrap();
848        0x0304u16.encode(&mut w).unwrap();
849        0x0506u16.encode(&mut w).unwrap();
850
851        let mut buf = bytes::Bytes::copy_from_slice(w.as_slice());
852        assert_eq!(
853            bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap(),
854            0x0102
855        );
856        assert_eq!(
857            bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap(),
858            0x0304
859        );
860        assert_eq!(
861            bytes_impl::decode_from_bytes::<u16>(&mut buf).unwrap(),
862            0x0506
863        );
864    }
865}