redoubt_codec_core/
decode_buffer.rs

1// Copyright (c) 2025-2026 Federico Hoerth <memparanoid@gmail.com>
2// SPDX-License-Identifier: GPL-3.0-only
3// See LICENSE in the repository root for full license text.
4
5use super::error::DecodeBufferError;
6use super::traits::DecodeBuffer;
7
8impl DecodeBuffer for &mut [u8] {
9    #[inline(always)]
10    fn read_usize(&mut self, dst: &mut usize) -> Result<(), DecodeBufferError> {
11        let size = core::mem::size_of::<usize>();
12
13        if self.len() < size {
14            return Err(DecodeBufferError::OutOfBounds);
15        }
16
17        // Native endian copy - no conversion
18        unsafe {
19            core::ptr::copy_nonoverlapping(self.as_ptr(), dst as *mut usize as *mut u8, size);
20        }
21
22        // Zeroize the Buffer
23        #[cfg(feature = "zeroize")]
24        redoubt_util::fast_zeroize_slice(&mut self[..size]);
25
26        // Shrink the slice - consume the bytes we read
27        *self = &mut core::mem::take(self)[size..];
28
29        Ok(())
30    }
31
32    #[inline(always)]
33    fn read<T>(&mut self, dst: &mut T) -> Result<(), DecodeBufferError> {
34        let len = core::mem::size_of::<T>();
35
36        if self.len() < len {
37            return Err(DecodeBufferError::OutOfBounds);
38        }
39
40        unsafe {
41            core::ptr::copy_nonoverlapping(self.as_ptr(), dst as *mut T as *mut u8, len);
42        }
43
44        // Zeroize the Buffer
45        #[cfg(feature = "zeroize")]
46        redoubt_util::fast_zeroize_slice(&mut self[..len]);
47
48        // Shrink the slice - consume the bytes we read
49        *self = &mut core::mem::take(self)[len..];
50
51        Ok(())
52    }
53
54    #[inline(always)]
55    fn read_slice<T>(&mut self, dst: &mut [T]) -> Result<(), DecodeBufferError> {
56        let byte_len = core::mem::size_of_val(dst);
57
58        if self.len() < byte_len {
59            return Err(DecodeBufferError::OutOfBounds);
60        }
61
62        unsafe {
63            core::ptr::copy_nonoverlapping(self.as_ptr(), dst.as_mut_ptr() as *mut u8, byte_len);
64        }
65
66        // Zeroize the Buffer
67        #[cfg(feature = "zeroize")]
68        redoubt_util::fast_zeroize_slice(&mut self[..byte_len]);
69
70        // Shrink the slice - consume the bytes we read
71        *self = &mut core::mem::take(self)[byte_len..];
72
73        Ok(())
74    }
75}