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