algorithm/buf/
binary_ref.rs1use std::fmt::Debug;
14use std::io::{self, Error};
15use std::marker::PhantomData;
16use std::ops::Deref;
17use std::{borrow::Borrow, cmp, hash, io::Read, io::Result, slice};
18
19use super::Binary;
20
21use super::Bt;
22
23static EMPTY_ARRAY: &[u8] = &[];
24
25pub struct BinaryRef<'a> {
27 ptr: *const u8,
28 cursor: usize,
30 mark: usize,
32 len: usize,
34
35 data: PhantomData<&'a ()>,
36}
37
38impl<'a> BinaryRef<'a> {
39 pub fn new() -> BinaryRef<'a> {
40 BinaryRef::from(EMPTY_ARRAY)
41 }
42
43 pub fn len(&self) -> usize {
53 self.len
54 }
55
56 #[inline]
67 pub const fn is_empty(&self) -> bool {
68 self.len == 0
69 }
70
71 pub fn to_vec(&self) -> Vec<u8> {
72 unsafe { slice::from_raw_parts(self.ptr, self.len).to_vec() }
73 }
74
75 #[inline]
76 fn as_slice(&self) -> &[u8] {
77 unsafe { slice::from_raw_parts(self.ptr, self.len) }
78 }
79
80 #[inline]
81 unsafe fn inc_start(&mut self, by: usize) {
82 if by == 0 {
83 return;
84 }
85 debug_assert!(self.len >= by, "internal: inc_start out of bounds");
87 self.len -= by;
88 self.ptr = self.ptr.add(by);
89 self.cursor += by;
90 }
91
92 pub fn copy_from_slice(data: &'a [u8]) -> Self {
103 data.into()
104 }
105
106 #[inline]
107 pub fn into_slice_all(&self) -> Vec<u8> {
108 self.to_vec()
109 }
110}
111
112impl<'a> Clone for BinaryRef<'a> {
113 fn clone(&self) -> Self {
114 BinaryRef {
115 ptr: self.ptr,
116 cursor: self.cursor,
117 mark: self.mark,
118 len: self.len,
119 data: self.data.clone(),
120 }
121 }
122}
123
124impl<'a> Drop for BinaryRef<'a> {
125 fn drop(&mut self) {}
126}
127
128impl<'a> From<&'a str> for BinaryRef<'a> {
129 fn from(value: &'a str) -> Self {
130 BinaryRef::from(value.as_bytes())
131 }
132}
133
134impl<'a> From<&'a [u8]> for BinaryRef<'a> {
135 fn from(value: &'a [u8]) -> Self {
136 let len = value.len();
137 BinaryRef {
138 ptr: value.as_ptr(),
139 len,
140 mark: 0,
141 cursor: 0,
142 data: PhantomData,
143 }
144 }
145}
146
147impl<'a> Bt for BinaryRef<'a> {
148 fn remaining(&self) -> usize {
149 self.len
150 }
151
152 fn chunk(&self) -> &[u8] {
153 self.as_slice()
154 }
155
156 fn advance_chunk(&mut self, n: usize) -> &[u8] {
157 let ret = &unsafe { slice::from_raw_parts(self.ptr, self.len) }[..n];
158 self.advance(n);
159 ret
160 }
161
162 fn advance(&mut self, n: usize) {
163 unsafe {
164 self.inc_start(n);
165 }
166 }
167
168 fn into_binary(self) -> Binary {
169 Binary::from(self.chunk().to_vec())
170 }
171}
172
173impl<'a> Read for BinaryRef<'a> {
174 #[inline(always)]
175 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
176 let left = self.remaining();
177 if left == 0 || buf.len() == 0 {
178 return Err(Error::new(io::ErrorKind::WouldBlock, ""));
179 }
180 let read = std::cmp::min(left, buf.len());
181 unsafe {
182 std::ptr::copy(&self.chunk()[0], &mut buf[0], read);
183 }
184 self.advance(read);
185 Ok(read)
186 }
187}
188
189impl<'a> Iterator for BinaryRef<'a> {
190 type Item = u8;
191 #[inline]
192 fn next(&mut self) -> Option<u8> {
193 self.get_next()
194 }
195}
196
197impl<'a> Deref for BinaryRef<'a> {
198 type Target = [u8];
199
200 #[inline]
201 fn deref(&self) -> &[u8] {
202 self.as_slice()
203 }
204}
205
206impl<'a> Debug for BinaryRef<'a> {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 f.debug_struct("Binary")
209 .field("ptr", &self.ptr)
210 .field("cursor", &self.cursor)
211 .field("mark", &self.mark)
212 .field("len", &self.len)
213 .finish()
214 }
215}
216
217impl<'a> AsRef<[u8]> for BinaryRef<'a> {
218 #[inline]
219 fn as_ref(&self) -> &[u8] {
220 self.as_slice()
221 }
222}
223
224impl<'a> hash::Hash for BinaryRef<'a> {
225 fn hash<H>(&self, state: &mut H)
226 where
227 H: hash::Hasher,
228 {
229 self.as_slice().hash(state);
230 }
231}
232
233impl<'a> Borrow<[u8]> for BinaryRef<'a> {
234 fn borrow(&self) -> &[u8] {
235 self.as_slice()
236 }
237}
238
239impl<'a> PartialEq for BinaryRef<'a> {
240 fn eq(&self, other: &BinaryRef) -> bool {
241 self.as_slice() == other.as_slice()
242 }
243}
244
245impl<'a> PartialOrd for BinaryRef<'a> {
246 fn partial_cmp(&self, other: &BinaryRef) -> Option<cmp::Ordering> {
247 self.as_slice().partial_cmp(other.as_slice())
248 }
249}
250
251impl<'a> Ord for BinaryRef<'a> {
252 fn cmp(&self, other: &BinaryRef) -> cmp::Ordering {
253 self.as_slice().cmp(other.as_slice())
254 }
255}
256
257impl<'a> Eq for BinaryRef<'a> {}
258
259impl<'a> PartialEq<[u8]> for BinaryRef<'a> {
260 fn eq(&self, other: &[u8]) -> bool {
261 self.as_slice() == other
262 }
263}
264
265impl<'a> PartialOrd<[u8]> for BinaryRef<'a> {
266 fn partial_cmp(&self, other: &[u8]) -> Option<cmp::Ordering> {
267 self.as_slice().partial_cmp(other)
268 }
269}
270
271impl<'a> PartialEq<BinaryRef<'a>> for [u8] {
272 fn eq(&self, other: &BinaryRef) -> bool {
273 *other == *self
274 }
275}
276
277impl<'a> PartialOrd<BinaryRef<'a>> for [u8] {
278 fn partial_cmp(&self, other: &BinaryRef) -> Option<cmp::Ordering> {
279 <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
280 }
281}
282
283impl<'a> PartialEq<str> for BinaryRef<'a> {
284 fn eq(&self, other: &str) -> bool {
285 self.as_slice() == other.as_bytes()
286 }
287}
288
289impl<'a> PartialOrd<str> for BinaryRef<'a> {
290 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
291 self.as_slice().partial_cmp(other.as_bytes())
292 }
293}
294
295impl<'a> PartialEq<BinaryRef<'a>> for str {
296 fn eq(&self, other: &BinaryRef) -> bool {
297 *other == *self
298 }
299}
300
301impl<'a> PartialOrd<BinaryRef<'a>> for str {
302 fn partial_cmp(&self, other: &BinaryRef) -> Option<cmp::Ordering> {
303 <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
304 }
305}
306
307impl<'a> PartialEq<Vec<u8>> for BinaryRef<'a> {
308 fn eq(&self, other: &Vec<u8>) -> bool {
309 *self == other[..]
310 }
311}
312
313impl<'a> PartialOrd<Vec<u8>> for BinaryRef<'a> {
314 fn partial_cmp(&self, other: &Vec<u8>) -> Option<cmp::Ordering> {
315 self.as_slice().partial_cmp(&other[..])
316 }
317}
318
319impl<'a> PartialEq<BinaryRef<'a>> for Vec<u8> {
320 fn eq(&self, other: &BinaryRef) -> bool {
321 *other == *self
322 }
323}
324
325impl<'a> PartialOrd<BinaryRef<'a>> for Vec<u8> {
326 fn partial_cmp(&self, other: &BinaryRef) -> Option<cmp::Ordering> {
327 <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
328 }
329}
330
331impl<'a> PartialEq<String> for BinaryRef<'a> {
332 fn eq(&self, other: &String) -> bool {
333 *self == other[..]
334 }
335}
336
337impl<'a> PartialOrd<String> for BinaryRef<'a> {
338 fn partial_cmp(&self, other: &String) -> Option<cmp::Ordering> {
339 self.as_slice().partial_cmp(other.as_bytes())
340 }
341}
342
343impl<'a> PartialEq<BinaryRef<'a>> for String {
344 fn eq(&self, other: &BinaryRef) -> bool {
345 *other == *self
346 }
347}
348
349impl<'a> PartialOrd<BinaryRef<'a>> for String {
350 fn partial_cmp(&self, other: &BinaryRef) -> Option<cmp::Ordering> {
351 <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
352 }
353}
354
355impl<'a> PartialEq<BinaryRef<'a>> for &[u8] {
356 fn eq(&self, other: &BinaryRef) -> bool {
357 *other == *self
358 }
359}
360
361impl<'a> PartialOrd<BinaryRef<'a>> for &[u8] {
362 fn partial_cmp(&self, other: &BinaryRef) -> Option<cmp::Ordering> {
363 <[u8] as PartialOrd<[u8]>>::partial_cmp(self, other)
364 }
365}
366
367impl<'a> PartialEq<BinaryRef<'a>> for &str {
368 fn eq(&self, other: &BinaryRef) -> bool {
369 *other == *self
370 }
371}
372
373impl<'a> PartialOrd<BinaryRef<'a>> for &str {
374 fn partial_cmp(&self, other: &BinaryRef) -> Option<cmp::Ordering> {
375 <[u8] as PartialOrd<[u8]>>::partial_cmp(self.as_bytes(), other)
376 }
377}
378
379impl<'a, T: ?Sized> PartialEq<&'a T> for BinaryRef<'a>
380where
381 BinaryRef<'a>: PartialEq<T>,
382{
383 fn eq(&self, other: &&'a T) -> bool {
384 *self == **other
385 }
386}
387
388impl<'a, T: ?Sized> PartialOrd<&'a T> for BinaryRef<'a>
389where
390 BinaryRef<'a>: PartialOrd<T>,
391{
392 fn partial_cmp(&self, other: &&'a T) -> Option<cmp::Ordering> {
393 self.partial_cmp(&**other)
394 }
395}
396
397impl<'a> Default for BinaryRef<'a> {
400 #[inline]
401 fn default() -> BinaryRef<'a> {
402 BinaryRef::new()
403 }
404}
405
406#[cfg(test)]
407mod tests {
408 use super::{BinaryRef, Bt};
409
410 #[test]
411 fn binary_refs() {
412 {
413 let s = BinaryRef::from("aaaa");
414 let s1 = s.clone();
415 drop(s1);
416 }
417 {
418 let v = vec![1, 2];
419 let mut b = BinaryRef::from(&v[..]);
420 let x = b.get_u8();
421 assert!(x == 1);
422 let b1 = b.clone();
423 drop(b1);
424 }
425 }
426}