1use core::slice;
2use core::convert::TryInto;
3use core::convert::TryFrom;
4
5pub struct Bytes<'a> {
6 slice: &'a [u8],
7 pos: usize
8}
9
10impl<'a> Bytes<'a> {
11 #[inline]
12 pub fn new(slice: &'a [u8]) -> Bytes<'a> {
13 Bytes {
14 slice,
15 pos: 0
16 }
17 }
18
19 #[inline]
20 pub fn pos(&self) -> usize {
21 self.pos
22 }
23
24 #[inline]
25 pub fn peek(&self) -> Option<u8> {
26 self.peek_ahead(0)
27 }
28
29 #[inline]
30 pub fn peek_ahead(&self, n: usize) -> Option<u8> {
31 self.slice.get(self.pos + n).copied()
32 }
33
34 #[inline]
35 pub fn peek_n<U: TryFrom<&'a[u8]>>(&self, n: usize) -> Option<U> {
36 self.slice.get(self.pos..self.pos + n)?.try_into().ok()
37 }
38
39 #[inline]
40 pub unsafe fn bump(&mut self) {
41 debug_assert!(self.pos < self.slice.len(), "overflow");
42 self.pos += 1;
43 }
44
45 #[allow(unused)]
46 #[inline]
47 pub unsafe fn advance(&mut self, n: usize) {
48 debug_assert!(self.pos + n <= self.slice.len(), "overflow");
49 self.pos += n;
50 }
51
52 #[inline]
53 pub fn len(&self) -> usize {
54 self.slice.len()
55 }
56
57 #[inline]
58 pub fn slice(&mut self) -> &'a [u8] {
59 // not moving position at all, so it's safe
60 unsafe {
61 self.slice_skip(0)
62 }
63 }
64
65 #[inline]
66 pub unsafe fn slice_skip(&mut self, skip: usize) -> &'a [u8] {
67 debug_assert!(self.pos >= skip);
68 let head_pos = self.pos - skip;
69 let ptr = self.slice.as_ptr();
70 let head = slice::from_raw_parts(ptr, head_pos);
71 let tail = slice::from_raw_parts(ptr.add(self.pos), self.slice.len() - self.pos);
72 self.pos = 0;
73 self.slice = tail;
74 head
75 }
76
77 #[inline]
78 pub unsafe fn advance_and_commit(&mut self, n: usize) {
79 debug_assert!(self.pos + n <= self.slice.len(), "overflow");
80 self.pos += n;
81 let ptr = self.slice.as_ptr();
82 let tail = slice::from_raw_parts(ptr.add(n), self.slice.len() - n);
83 self.pos = 0;
84 self.slice = tail;
85 }
86}
87
88impl<'a> AsRef<[u8]> for Bytes<'a> {
89 #[inline]
90 fn as_ref(&self) -> &[u8] {
91 &self.slice[self.pos..]
92 }
93}
94
95impl<'a> Iterator for Bytes<'a> {
96 type Item = u8;
97
98 #[inline]
99 fn next(&mut self) -> Option<u8> {
100 if self.slice.len() > self.pos {
101 let b = unsafe { *self.slice.get_unchecked(self.pos) };
102 self.pos += 1;
103 Some(b)
104 } else {
105 None
106 }
107 }
108}
109