1use core::slice;
2
3pub struct Bytes<'a> {
4 slice: &'a [u8],
5 pos: usize
6}
7
8impl<'a> Bytes<'a> {
9 #[inline]
10 pub fn new(slice: &'a [u8]) -> Bytes<'a> {
11 Bytes {
12 slice: slice,
13 pos: 0
14 }
15 }
16
17 #[inline]
18 pub fn pos(&self) -> usize {
19 self.pos
20 }
21
22 #[inline]
23 pub fn peek(&self) -> Option<u8> {
24 self.slice.get(self.pos).cloned()
25 }
26
27 #[inline]
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]
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]
41 pub fn len(&self) -> usize {
42 self.slice.len()
43 }
44
45 #[inline]
46 pub fn slice(&mut self) -> &'a [u8] {
47 unsafe {
49 self.slice_skip(0)
50 }
51 }
52
53 #[inline]
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]
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
75impl<'a> AsRef<[u8]> for Bytes<'a> {
76 #[inline]
77 fn as_ref(&self) -> &[u8] {
78 &self.slice[self.pos..]
79 }
80}
81
82impl<'a> Iterator for Bytes<'a> {
83 type Item = u8;
84
85 #[inline]
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
97pub struct Bytes8<'a, 'b: 'a> {
98 bytes: &'a mut Bytes<'b>,
99 #[cfg(debug_assertions)]
100 pos: usize
101}
102
103macro_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
125impl<'a, 'b: 'a> Bytes8<'a, 'b> {
126 bytes8_methods! {}
127
128 #[cfg(not(debug_assertions))]
129 #[inline]
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]
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]
147 fn assert_pos(&mut self, _pos: usize) {
148 }
149
150 #[cfg(debug_assertions)]
151 #[inline]
152 fn assert_pos(&mut self, pos: usize) {
153 assert!(self.pos == pos);
154 self.pos += 1;
155 }
156}