1#[cfg(test)]
2mod tests;
3
4use nom::{AsBytes, Compare, CompareResult, InputIter, InputLength, InputTake, Offset, Slice};
5use std::ops::{RangeFrom, RangeTo};
6
7#[derive(Debug, Clone, Copy)]
11pub struct BinarySpan<T> {
12 offset: usize,
13 fragment: T,
14}
15
16impl<T> BinarySpan<T> {
17 pub const fn new(buffer: T) -> Self {
18 Self {
19 offset: 0,
20 fragment: buffer,
21 }
22 }
23
24 pub const unsafe fn new_from_raw_offset(offset: usize, fragment: T) -> Self {
30 Self { offset, fragment }
31 }
32
33 pub const fn new_extra(program: T) -> BinarySpan<T> {
34 BinarySpan {
35 offset: 0,
36 fragment: program,
37 }
38 }
39
40 #[inline]
41 pub const fn location_offset(&self) -> usize {
42 self.offset
43 }
44
45 #[inline]
46 pub const fn fragment(&self) -> &T {
47 &self.fragment
48 }
49}
50
51impl<T, R> Slice<R> for BinarySpan<T>
52where
53 T: Slice<R> + Offset + AsBytes + Slice<RangeTo<usize>>,
54{
55 #[inline]
56 fn slice(&self, range: R) -> Self {
57 let next_fragment = self.fragment.slice(range);
58 let consumed_len = self.fragment.offset(&next_fragment);
59 if consumed_len == 0 {
60 return BinarySpan {
61 offset: self.offset,
62 fragment: next_fragment,
63 };
64 }
65
66 BinarySpan {
67 offset: self.offset + consumed_len,
68 fragment: next_fragment,
69 }
70 }
71}
72
73impl<T> InputIter for BinarySpan<T>
74where
75 T: InputIter,
76{
77 type Item = T::Item;
78 type Iter = T::Iter;
79 type IterElem = T::IterElem;
80 #[inline]
81 fn iter_indices(&self) -> Self::Iter {
82 self.fragment.iter_indices()
83 }
84 #[inline]
85 fn iter_elements(&self) -> Self::IterElem {
86 self.fragment.iter_elements()
87 }
88 #[inline]
89 fn position<P>(&self, predicate: P) -> Option<usize>
90 where
91 P: Fn(Self::Item) -> bool,
92 {
93 self.fragment.position(predicate)
94 }
95 #[inline]
96 fn slice_index(&self, count: usize) -> Result<usize, nom::Needed> {
97 self.fragment.slice_index(count)
98 }
99}
100
101impl<T: InputLength> InputLength for BinarySpan<T> {
102 #[inline]
103 fn input_len(&self) -> usize {
104 self.fragment.input_len()
105 }
106}
107
108impl<T> InputTake for BinarySpan<T>
109where
110 Self: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
111{
112 #[inline]
113 fn take(&self, count: usize) -> Self {
114 self.slice(..count)
115 }
116
117 #[inline]
118 fn take_split(&self, count: usize) -> (Self, Self) {
119 (self.slice(count..), self.slice(..count))
120 }
121}
122
123impl<T> core::ops::Deref for BinarySpan<T> {
124 type Target = T;
125 fn deref(&self) -> &Self::Target {
126 &self.fragment
127 }
128}
129
130impl<T, U> AsRef<U> for BinarySpan<&T>
131where
132 T: ?Sized + AsRef<U>,
133 U: ?Sized,
134{
135 fn as_ref(&self) -> &U {
136 self.fragment.as_ref()
137 }
138}
139
140impl<T: AsBytes> AsBytes for BinarySpan<T> {
141 #[inline]
142 fn as_bytes(&self) -> &[u8] {
143 self.fragment.as_bytes()
144 }
145}
146
147impl<T: AsBytes + PartialEq> PartialEq for BinarySpan<T> {
148 #[inline]
149 fn eq(&self, other: &Self) -> bool {
150 self.offset == other.offset && self.fragment == other.fragment
151 }
152}
153
154impl<T: AsBytes + Eq> Eq for BinarySpan<T> {}
155
156impl<A: Compare<B>, B: Into<BinarySpan<B>>> Compare<B> for BinarySpan<A> {
157 #[inline(always)]
158 fn compare(&self, t: B) -> CompareResult {
159 self.fragment.compare(t.into().fragment)
160 }
161
162 #[inline(always)]
163 fn compare_no_case(&self, t: B) -> CompareResult {
164 self.fragment.compare_no_case(t.into().fragment)
165 }
166}
167
168impl<T: AsBytes> From<T> for BinarySpan<T> {
169 #[inline]
170 fn from(i: T) -> Self {
171 Self::new_extra(i)
172 }
173}
174
175#[test]
176fn it_should_implement_as_ref_for_the_underlying_type() {
177 fn function_accepting_u8_slice<B: AsRef<[u8]>>(_data: B) {}
178 let bytes_data = BinarySpan::new(b"some binary data");
179 function_accepting_u8_slice(bytes_data);
180}