modular_bitfield/private/
proc.rs

1use crate::{
2    private::{
3        PopBits,
4        PopBuffer,
5        PushBits,
6        PushBuffer,
7    },
8    Specifier,
9};
10
11/// Creates a new push buffer with all bits initialized to 0.
12#[inline]
13fn push_buffer<T>() -> PushBuffer<<T as Specifier>::Bytes>
14where
15    T: Specifier,
16    PushBuffer<T::Bytes>: Default,
17{
18    <PushBuffer<<T as Specifier>::Bytes> as Default>::default()
19}
20
21#[doc(hidden)]
22#[inline]
23pub fn read_specifier<T>(bytes: &[u8], offset: usize) -> <T as Specifier>::Bytes
24where
25    T: Specifier,
26    PushBuffer<T::Bytes>: Default + PushBits,
27{
28    let end = offset + <T as Specifier>::BITS;
29    let ls_byte = offset / 8; // compile-time
30    let ms_byte = (end - 1) / 8; // compile-time
31    let lsb_offset = offset % 8; // compile-time
32    let msb_offset = end % 8; // compile-time
33    let msb_offset = if msb_offset == 0 { 8 } else { msb_offset };
34
35    let mut buffer = push_buffer::<T>();
36
37    if lsb_offset == 0 && msb_offset == 8 {
38        // Edge-case for whole bytes manipulation.
39        for byte in bytes[ls_byte..(ms_byte + 1)].iter().rev() {
40            buffer.push_bits(8, *byte)
41        }
42    } else {
43        if ls_byte != ms_byte {
44            // Most-significant byte
45            buffer.push_bits(msb_offset as u32, bytes[ms_byte]);
46        }
47        if ms_byte - ls_byte >= 2 {
48            // Middle bytes
49            for byte in bytes[(ls_byte + 1)..ms_byte].iter().rev() {
50                buffer.push_bits(8, *byte);
51            }
52        }
53        if ls_byte == ms_byte {
54            buffer.push_bits(<T as Specifier>::BITS as u32, bytes[ls_byte] >> lsb_offset);
55        } else {
56            buffer.push_bits(8 - lsb_offset as u32, bytes[ls_byte] >> lsb_offset);
57        }
58    }
59    buffer.into_bytes()
60}
61
62#[doc(hidden)]
63#[inline]
64pub fn write_specifier<T>(
65    bytes: &mut [u8],
66    offset: usize,
67    new_val: <T as Specifier>::Bytes,
68) where
69    T: Specifier,
70    PopBuffer<T::Bytes>: PopBits,
71{
72    let end = offset + <T as Specifier>::BITS;
73    let ls_byte = offset / 8; // compile-time
74    let ms_byte = (end - 1) / 8; // compile-time
75    let lsb_offset = offset % 8; // compile-time
76    let msb_offset = end % 8; // compile-time
77    let msb_offset = if msb_offset == 0 { 8 } else { msb_offset };
78
79    let mut buffer = <PopBuffer<T::Bytes>>::from_bytes(new_val);
80
81    if lsb_offset == 0 && msb_offset == 8 {
82        // Edge-case for whole bytes manipulation.
83        for byte in bytes[ls_byte..(ms_byte + 1)].iter_mut() {
84            *byte = buffer.pop_bits(8);
85        }
86    } else {
87        // Least-significant byte
88        let stays_same = bytes[ls_byte]
89            & (if ls_byte == ms_byte && msb_offset != 8 {
90                !((0x01 << msb_offset) - 1)
91            } else {
92                0u8
93            } | ((0x01 << lsb_offset as u32) - 1));
94        let overwrite = buffer.pop_bits(8 - lsb_offset as u32);
95        bytes[ls_byte] = stays_same | (overwrite << lsb_offset as u32);
96        if ms_byte - ls_byte >= 2 {
97            // Middle bytes
98            for byte in bytes[(ls_byte + 1)..ms_byte].iter_mut() {
99                *byte = buffer.pop_bits(8);
100            }
101        }
102        if ls_byte != ms_byte {
103            // Most-significant byte
104            if msb_offset == 8 {
105                // We don't need to respect what was formerly stored in the byte.
106                bytes[ms_byte] = buffer.pop_bits(msb_offset as u32);
107            } else {
108                // All bits that do not belong to this field should be preserved.
109                let stays_same = bytes[ms_byte] & !((0x01 << msb_offset) - 1);
110                let overwrite = buffer.pop_bits(msb_offset as u32);
111                bytes[ms_byte] = stays_same | overwrite;
112            }
113        }
114    }
115}