pigeon/
unaligned_slice.rs1use core::cmp::{Eq, PartialEq};
2
3#[derive(Debug, Clone, Copy)]
5pub struct UnalignedSlice<'a> {
6 bytes: &'a [u8],
7 bit_offset: u32,
8}
9
10impl<'a> Eq for UnalignedSlice<'a> {}
11
12impl<'a> PartialEq for UnalignedSlice<'a> {
13 fn eq(&self, other: &UnalignedSlice<'a>) -> bool {
14 let mut iter_self = self.iter();
15 let mut iter_other = other.iter();
16 loop {
17 let byte_self = iter_self.next();
18 let byte_other = iter_other.next();
19 if byte_self != byte_other {
20 return false;
21 }
22 if byte_self.is_none() {
23 return true;
24 }
25 }
26 }
27}
28
29impl<'a> PartialEq<&'a [u8]> for UnalignedSlice<'a> {
30 fn eq(&self, other: &&'a [u8]) -> bool {
31 self.eq(&UnalignedSlice::new(other, 0))
32 }
33}
34
35impl<'a> UnalignedSlice<'a> {
36 pub fn new(bytes: &'a [u8], bit_offset: u32) -> Self {
38 Self { bytes, bit_offset }
39 }
40
41 pub fn len(&self) -> usize {
43 let extra_byte = if self.bit_offset == 0 { 0 } else { 1 };
44 self.bytes.len() - extra_byte
45 }
46
47 pub fn copy_to_slice(&self, buf: &mut [u8]) {
49 assert_eq!(self.len(), buf.len());
50 for (idx, byte) in self.iter().enumerate() {
51 buf[idx] = byte;
52 }
53 }
54
55 pub fn iter(&self) -> Iter<'a> {
57 let mut iter = self.bytes.iter();
58 let (mask_first, mask_second, last) = if self.bit_offset == 0 {
59 (0, 0xFF, 0)
60 } else {
61 let mask_first = 0xFF >> (8 - self.bit_offset);
62 let mask_second = 0xFF << self.bit_offset;
63 if let Some(&byte) = iter.next() {
64 (mask_first, mask_second, byte)
65 } else {
66 (mask_first, mask_second, 0)
67 }
68 };
69 Iter {
70 iter,
71 bit_offset: self.bit_offset,
72 mask_first,
73 mask_second,
74 last,
75 }
76 }
77}
78
79pub struct Iter<'a> {
81 iter: core::slice::Iter<'a, u8>,
82 bit_offset: u32,
83 mask_first: u8,
84 mask_second: u8,
85 last: u8,
86}
87
88impl<'a> Iterator for Iter<'a> {
89 type Item = u8;
90
91 fn next(&mut self) -> Option<Self::Item> {
92 if let Some(¤t) = self.iter.next() {
93 if self.bit_offset == 0 {
94 Some(current)
95 } else {
96 let fst = self.last & self.mask_first;
97 let snd = current & self.mask_second;
98 let byte = (fst | snd).rotate_right(self.bit_offset);
99 self.last = current;
100 Some(byte)
101 }
102 } else {
103 None
104 }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_unaligned_slice() {
114 let data = [0x12, 0x34, 0x56, 0x78];
115 let slice_a = UnalignedSlice::new(&data[1..3], 4);
116 assert_eq!(slice_a.len(), 1);
117 assert_eq!(slice_a, &[0x45][..]);
118 let slice_b = UnalignedSlice::new(&data[1..4], 4);
119 assert_eq!(slice_b.len(), 2);
120 assert_eq!(slice_b, &[0x45, 0x67][..]);
121 }
122
123 #[test]
124 fn test_unaligned_slice_iter() {
125 let data = [0x12, 0x34, 0x56, 0x78];
126 let slice = UnalignedSlice::new(&data[0..3], 4);
127 let mut iter = slice.iter();
128 assert_eq!(iter.next(), Some(0x23));
129 assert_eq!(iter.next(), Some(0x45));
130 assert_eq!(iter.next(), None);
131 }
132
133 #[test]
134 fn test_unaliged_slice_copy_to() {
135 let data = [0x12, 0x34, 0x56, 0x78];
136 let slice = UnalignedSlice::new(&data[0..3], 4);
137 let mut buf = [0; 2];
138 slice.copy_to_slice(&mut buf[..]);
139 assert_eq!(&buf[..2], &[0x23, 0x45]);
140 }
141}