1 use core::slice;
2 
3 pub struct Bytes<'a> {
4     slice: &'a [u8],
5     pos: usize
6 }
7 
8 impl<'a> Bytes<'a> {
9     #[inline]
new(slice: &'a [u8]) -> Bytes<'a>10     pub fn new(slice: &'a [u8]) -> Bytes<'a> {
11         Bytes {
12             slice: slice,
13             pos: 0
14         }
15     }
16 
17     #[inline]
pos(&self) -> usize18     pub fn pos(&self) -> usize {
19         self.pos
20     }
21 
22     #[inline]
peek(&self) -> Option<u8>23     pub fn peek(&self) -> Option<u8> {
24         self.slice.get(self.pos).cloned()
25     }
26 
27     #[inline]
bump(&mut self)28     pub unsafe fn bump(&mut self) {
29         debug_assert!(self.pos + 1 <= self.slice.len(), "overflow");
30         self.pos += 1;
31     }
32 
33     #[allow(unused)]
34     #[inline]
advance(&mut self, n: usize)35     pub unsafe fn advance(&mut self, n: usize) {
36         debug_assert!(self.pos + n <= self.slice.len(), "overflow");
37         self.pos += n;
38     }
39 
40     #[inline]
len(&self) -> usize41     pub fn len(&self) -> usize {
42         self.slice.len()
43     }
44 
45     #[inline]
slice(&mut self) -> &'a [u8]46     pub fn slice(&mut self) -> &'a [u8] {
47         // not moving position at all, so it's safe
48         unsafe {
49             self.slice_skip(0)
50         }
51     }
52 
53     #[inline]
slice_skip(&mut self, skip: usize) -> &'a [u8]54     pub unsafe fn slice_skip(&mut self, skip: usize) -> &'a [u8] {
55         debug_assert!(self.pos >= skip);
56         let head_pos = self.pos - skip;
57         let ptr = self.slice.as_ptr();
58         let head = slice::from_raw_parts(ptr, head_pos);
59         let tail = slice::from_raw_parts(ptr.offset(self.pos as isize), self.slice.len() - self.pos);
60         self.pos = 0;
61         self.slice = tail;
62         head
63     }
64 
65     #[inline]
next_8<'b>(&'b mut self) -> Option<Bytes8<'b, 'a>>66     pub fn next_8<'b>(&'b mut self) -> Option<Bytes8<'b, 'a>> {
67         if self.slice.len() >= self.pos + 8 {
68             Some(Bytes8::new(self))
69         } else {
70             None
71         }
72     }
73 }
74 
75 impl<'a> AsRef<[u8]> for Bytes<'a> {
76     #[inline]
as_ref(&self) -> &[u8]77     fn as_ref(&self) -> &[u8] {
78         &self.slice[self.pos..]
79     }
80 }
81 
82 impl<'a> Iterator for Bytes<'a> {
83     type Item = u8;
84 
85     #[inline]
next(&mut self) -> Option<u8>86     fn next(&mut self) -> Option<u8> {
87         if self.slice.len() > self.pos {
88             let b = unsafe { *self.slice.get_unchecked(self.pos) };
89             self.pos += 1;
90             Some(b)
91         } else {
92             None
93         }
94     }
95 }
96 
97 pub struct Bytes8<'a, 'b: 'a> {
98     bytes: &'a mut Bytes<'b>,
99     #[cfg(debug_assertions)]
100     pos: usize
101 }
102 
103 macro_rules! bytes8_methods {
104     ($f:ident, $pos:expr) => {
105         #[inline]
106         pub fn $f(&mut self) -> u8 {
107             self.assert_pos($pos);
108             let b = unsafe { *self.bytes.slice.get_unchecked(self.bytes.pos) };
109             self.bytes.pos += 1;
110             b
111         }
112     };
113     () => {
114         bytes8_methods!(_0, 0);
115         bytes8_methods!(_1, 1);
116         bytes8_methods!(_2, 2);
117         bytes8_methods!(_3, 3);
118         bytes8_methods!(_4, 4);
119         bytes8_methods!(_5, 5);
120         bytes8_methods!(_6, 6);
121         bytes8_methods!(_7, 7);
122     }
123 }
124 
125 impl<'a, 'b: 'a> Bytes8<'a, 'b> {
126     bytes8_methods! {}
127 
128     #[cfg(not(debug_assertions))]
129     #[inline]
new(bytes: &'a mut Bytes<'b>) -> Bytes8<'a, 'b>130     fn new(bytes: &'a mut Bytes<'b>) -> Bytes8<'a, 'b> {
131         Bytes8 {
132             bytes: bytes,
133         }
134     }
135 
136     #[cfg(debug_assertions)]
137     #[inline]
new(bytes: &'a mut Bytes<'b>) -> Bytes8<'a, 'b>138     fn new(bytes: &'a mut Bytes<'b>) -> Bytes8<'a, 'b> {
139         Bytes8 {
140             bytes: bytes,
141             pos: 0,
142         }
143     }
144 
145     #[cfg(not(debug_assertions))]
146     #[inline]
assert_pos(&mut self, _pos: usize)147     fn assert_pos(&mut self, _pos: usize) {
148     }
149 
150     #[cfg(debug_assertions)]
151     #[inline]
assert_pos(&mut self, pos: usize)152     fn assert_pos(&mut self, pos: usize) {
153         assert!(self.pos == pos);
154         self.pos += 1;
155     }
156 }
157 
158 #[cfg(test)]
159 mod tests {
160     use super::Bytes;
161 
162     #[test]
test_next_8_too_short()163     fn test_next_8_too_short() {
164         // Start with 10 bytes.
165         let slice = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
166         let mut bytes = Bytes::new(&slice);
167         // Skip 3 of them.
168         unsafe { bytes.advance(3); }
169         // There should be 7 left, not enough to call next_8.
170         assert!(bytes.next_8().is_none());
171     }
172 
173     #[test]
test_next_8_just_right()174     fn test_next_8_just_right() {
175         // Start with 10 bytes.
176         let slice = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
177         let mut bytes = Bytes::new(&slice);
178         // Skip 2 of them.
179         unsafe { bytes.advance(2); }
180         // There should be 8 left, just enough to call next_8.
181         let ret = bytes.next_8();
182         assert!(ret.is_some());
183         let mut ret = ret.unwrap();
184         // They should be the bytes starting with 2.
185         assert_eq!(ret._0(), 2u8);
186         assert_eq!(ret._1(), 3u8);
187         assert_eq!(ret._2(), 4u8);
188         assert_eq!(ret._3(), 5u8);
189         assert_eq!(ret._4(), 6u8);
190         assert_eq!(ret._5(), 7u8);
191         assert_eq!(ret._6(), 8u8);
192         assert_eq!(ret._7(), 9u8);
193     }
194 
195     #[test]
test_next_8_extra()196     fn test_next_8_extra() {
197         // Start with 10 bytes.
198         let slice = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
199         let mut bytes = Bytes::new(&slice);
200         // Skip 1 of them.
201         unsafe { bytes.advance(1); }
202         // There should be 9 left, more than enough to call next_8.
203         let ret = bytes.next_8();
204         assert!(ret.is_some());
205         let mut ret = ret.unwrap();
206         // They should be the bytes starting with 1.
207         assert_eq!(ret._0(), 1u8);
208         assert_eq!(ret._1(), 2u8);
209         assert_eq!(ret._2(), 3u8);
210         assert_eq!(ret._3(), 4u8);
211         assert_eq!(ret._4(), 5u8);
212         assert_eq!(ret._5(), 6u8);
213         assert_eq!(ret._6(), 7u8);
214         assert_eq!(ret._7(), 8u8);
215     }
216 }
217