algorithm/buf/
binary_ref.rs

1// Copyright 2022 - 2023 Wenmeng See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8//
9// Author: tickbh
10// -----
11// Created Date: 2023/09/14 12:21:02
12
13use 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
25/// 二进制引用的封装, 只针对引用
26pub struct BinaryRef<'a> {
27    ptr: *const u8,
28    // 游标值, 可以得出当前指向的位置
29    cursor: usize,
30    // 标记值, 从上一次标记到现在的游标值, 可以得出偏移的对象
31    mark: usize,
32    // 长度值, 还剩下多少的长度
33    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    /// # Examples
44    ///
45    /// ```
46    /// use algorithm::buf::Binary;
47    ///
48    /// let b = Binary::from(&b"hello"[..]);
49    /// assert_eq!(b.len(), 5);
50    /// ```
51    ///
52    pub fn len(&self) -> usize {
53        self.len
54    }
55
56    /// Returns true if the `Binary` has a length of 0.
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use algorithm::buf::Binary;
62    ///
63    /// let b = Binary::new();
64    /// assert!(b.is_empty());
65    /// ```
66    #[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        // should already be asserted, but debug assert for tests
86        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    // #[inline]
93    // unsafe fn sub_start(&mut self, by: usize) {
94    //     // should already be asserted, but debug assert for tests
95    //     debug_assert!(self.cursor >= by, "internal: inc_start out of bounds");
96    //     self.len += by;
97    //     self.ptr = self.ptr.sub(by);
98    //     self.cursor -= by;
99    //     self.mark = std::cmp::min(self.mark, self.cursor);
100    // }
101
102    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
397// impl From
398
399impl<'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}