| 
1 |  | -use core::slice;  | 
2 |  | -use core::convert::TryInto;  | 
3 |  | -use core::convert::TryFrom;  | 
4 |  | - | 
5 | 1 | #[allow(missing_docs)]  | 
6 | 2 | pub struct Bytes<'a> {  | 
7 |  | -    slice: &'a [u8],  | 
8 |  | -    pos: usize  | 
 | 3 | +    start: *const u8,  | 
 | 4 | +    end: *const u8,  | 
 | 5 | +    cursor: *const u8,  | 
 | 6 | +    phantom: core::marker::PhantomData<&'a ()>,  | 
9 | 7 | }  | 
10 | 8 | 
 
  | 
11 | 9 | #[allow(missing_docs)]  | 
12 | 10 | impl<'a> Bytes<'a> {  | 
13 | 11 |     #[inline]  | 
14 | 12 |     pub fn new(slice: &'a [u8]) -> Bytes<'a> {  | 
 | 13 | +        let start = slice.as_ptr();  | 
 | 14 | +        let end = unsafe { start.add(slice.len()) };  | 
 | 15 | +        let cursor = start;  | 
15 | 16 |         Bytes {  | 
16 |  | -            slice,  | 
17 |  | -            pos: 0  | 
 | 17 | +            start,  | 
 | 18 | +            end,  | 
 | 19 | +            cursor,  | 
 | 20 | +            phantom: core::marker::PhantomData,  | 
18 | 21 |         }  | 
19 | 22 |     }  | 
20 | 23 | 
 
  | 
21 | 24 |     #[inline]  | 
22 | 25 |     pub fn pos(&self) -> usize {  | 
23 |  | -        self.pos  | 
 | 26 | +        self.cursor as usize - self.start as usize  | 
24 | 27 |     }  | 
25 | 28 | 
 
  | 
26 | 29 |     #[inline]  | 
27 | 30 |     pub fn peek(&self) -> Option<u8> {  | 
28 |  | -        self.peek_ahead(0)  | 
 | 31 | +        if self.cursor < self.end {  | 
 | 32 | +            // SAFETY: bounds checked  | 
 | 33 | +            Some(unsafe { *self.cursor })  | 
 | 34 | +        } else {  | 
 | 35 | +            None  | 
 | 36 | +        }  | 
29 | 37 |     }  | 
30 | 38 | 
 
  | 
31 | 39 |     #[inline]  | 
32 | 40 |     pub fn peek_ahead(&self, n: usize) -> Option<u8> {  | 
33 |  | -        self.slice.get(self.pos + n).copied()  | 
 | 41 | +        let ptr = unsafe { self.cursor.add(n) };  | 
 | 42 | +        if ptr < self.end {  | 
 | 43 | +            // SAFETY: bounds checked  | 
 | 44 | +            Some(unsafe { *ptr })  | 
 | 45 | +        } else {  | 
 | 46 | +            None  | 
 | 47 | +        }  | 
34 | 48 |     }  | 
35 |  | - | 
 | 49 | +      | 
36 | 50 |     #[inline]  | 
37 |  | -    pub fn peek_n<U: TryFrom<&'a[u8]>>(&self, n: usize) -> Option<U> {  | 
38 |  | -        self.slice.get(self.pos..self.pos + n)?.try_into().ok()  | 
 | 51 | +    pub fn peek_n<U>(&self) -> Option<U> {  | 
 | 52 | +        let n = core::mem::size_of::<U>();  | 
 | 53 | +        // Boundary check then read array from ptr  | 
 | 54 | +        if self.len() >= n {  | 
 | 55 | +            let ptr = self.cursor as *const U;  | 
 | 56 | +            let x = unsafe { core::ptr::read_unaligned(ptr) };  | 
 | 57 | +            Some(x)  | 
 | 58 | +        } else {  | 
 | 59 | +            None  | 
 | 60 | +        }  | 
39 | 61 |     }  | 
40 | 62 | 
 
  | 
41 | 63 |     #[inline]  | 
42 | 64 |     pub unsafe fn bump(&mut self) {  | 
43 |  | -        debug_assert!(self.pos < self.slice.len(), "overflow");  | 
44 |  | -        self.pos += 1;  | 
 | 65 | +        self.advance(1)  | 
45 | 66 |     }  | 
46 | 67 | 
 
  | 
47 |  | -    #[allow(unused)]  | 
48 | 68 |     #[inline]  | 
49 | 69 |     pub unsafe fn advance(&mut self, n: usize) {  | 
50 |  | -        debug_assert!(self.pos + n <= self.slice.len(), "overflow");  | 
51 |  | -        self.pos += n;  | 
 | 70 | +        self.cursor = self.cursor.add(n);  | 
 | 71 | +        debug_assert!(self.cursor <= self.end, "overflow");  | 
52 | 72 |     }  | 
53 | 73 | 
 
  | 
54 | 74 |     #[inline]  | 
55 | 75 |     pub fn len(&self) -> usize {  | 
56 |  | -        self.slice.len()  | 
 | 76 | +        self.end as usize - self.cursor as usize  | 
57 | 77 |     }  | 
58 | 78 | 
 
  | 
59 | 79 |     #[inline]  | 
60 | 80 |     pub fn slice(&mut self) -> &'a [u8] {  | 
61 | 81 |         // not moving position at all, so it's safe  | 
62 |  | -        unsafe {  | 
63 |  | -            self.slice_skip(0)  | 
64 |  | -        }  | 
 | 82 | +        let slice = unsafe { slice_from_ptr_range(self.start, self.cursor) };  | 
 | 83 | +        self.commit();  | 
 | 84 | +        slice  | 
65 | 85 |     }  | 
66 | 86 | 
 
  | 
 | 87 | +    // TODO: this is an anti-pattern, should be removed  | 
67 | 88 |     #[inline]  | 
68 | 89 |     pub unsafe fn slice_skip(&mut self, skip: usize) -> &'a [u8] {  | 
69 |  | -        debug_assert!(self.pos >= skip);  | 
70 |  | -        let head_pos = self.pos - skip;  | 
71 |  | -        let ptr = self.slice.as_ptr();  | 
72 |  | -        let head = slice::from_raw_parts(ptr, head_pos);  | 
73 |  | -        let tail = slice::from_raw_parts(ptr.add(self.pos), self.slice.len() - self.pos);  | 
74 |  | -        self.pos = 0;  | 
75 |  | -        self.slice = tail;  | 
 | 90 | +        debug_assert!(self.cursor.sub(skip) >= self.start);  | 
 | 91 | +        let head = slice_from_ptr_range(self.start, self.cursor.sub(skip));  | 
 | 92 | +        self.commit();  | 
76 | 93 |         head  | 
77 | 94 |     }  | 
 | 95 | +      | 
 | 96 | +    #[inline]  | 
 | 97 | +    pub fn commit(&mut self) {  | 
 | 98 | +        self.start = self.cursor  | 
 | 99 | +    }  | 
78 | 100 | 
 
  | 
79 | 101 |     #[inline]  | 
80 | 102 |     pub unsafe fn advance_and_commit(&mut self, n: usize) {  | 
81 |  | -        debug_assert!(self.pos + n <= self.slice.len(), "overflow");  | 
82 |  | -        self.pos += n;  | 
83 |  | -        let ptr = self.slice.as_ptr();  | 
84 |  | -        let tail = slice::from_raw_parts(ptr.add(n), self.slice.len() - n);  | 
85 |  | -        self.pos = 0;  | 
86 |  | -        self.slice = tail;  | 
 | 103 | +        self.advance(n);  | 
 | 104 | +        self.commit();  | 
 | 105 | +    }  | 
 | 106 | +      | 
 | 107 | +    #[inline]  | 
 | 108 | +    pub fn as_ptr(&self) -> *const u8 {  | 
 | 109 | +        self.cursor  | 
 | 110 | +    }  | 
 | 111 | + | 
 | 112 | +    #[inline]  | 
 | 113 | +    pub fn start(&self) -> *const u8 {  | 
 | 114 | +        self.start  | 
 | 115 | +    }  | 
 | 116 | +      | 
 | 117 | +    #[inline]  | 
 | 118 | +    pub fn end(&self) -> *const u8 {  | 
 | 119 | +        self.end  | 
 | 120 | +    }  | 
 | 121 | +      | 
 | 122 | +    #[inline]  | 
 | 123 | +    pub unsafe fn set_cursor(&mut self, ptr: *const u8) {  | 
 | 124 | +        debug_assert!(ptr >= self.start);  | 
 | 125 | +        debug_assert!(ptr <= self.end);  | 
 | 126 | +        self.cursor = ptr;  | 
87 | 127 |     }  | 
88 | 128 | }  | 
89 | 129 | 
 
  | 
90 | 130 | impl<'a> AsRef<[u8]> for Bytes<'a> {  | 
91 | 131 |     #[inline]  | 
92 | 132 |     fn as_ref(&self) -> &[u8] {  | 
93 |  | -        &self.slice[self.pos..]  | 
 | 133 | +        unsafe { slice_from_ptr_range(self.cursor, self.end) }  | 
94 | 134 |     }  | 
95 | 135 | }  | 
96 | 136 | 
 
  | 
 | 137 | +#[inline]  | 
 | 138 | +unsafe fn slice_from_ptr_range<'a>(start: *const u8, end: *const u8) -> &'a [u8] {  | 
 | 139 | +    debug_assert!(start <= end);  | 
 | 140 | +    core::slice::from_raw_parts(start, end as usize - start as usize)  | 
 | 141 | +}  | 
 | 142 | + | 
97 | 143 | impl<'a> Iterator for Bytes<'a> {  | 
98 | 144 |     type Item = u8;  | 
99 | 145 | 
 
  | 
100 | 146 |     #[inline]  | 
101 | 147 |     fn next(&mut self) -> Option<u8> {  | 
102 |  | -        if self.slice.len() > self.pos {  | 
103 |  | -            let b = unsafe { *self.slice.get_unchecked(self.pos) };  | 
104 |  | -            self.pos += 1;  | 
105 |  | -            Some(b)  | 
 | 148 | +        if self.cursor < self.end {  | 
 | 149 | +            // SAFETY: bounds checked  | 
 | 150 | +            unsafe {  | 
 | 151 | +                let b = *self.cursor;  | 
 | 152 | +                self.bump();  | 
 | 153 | +                Some(b)  | 
 | 154 | +            }  | 
106 | 155 |         } else {  | 
107 | 156 |             None  | 
108 | 157 |         }  | 
 | 
0 commit comments