• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::ops::{Deref, Range};
2 
3 /// The underlying buffer that is used by a flexbuffer Reader.
4 ///
5 /// This allows for custom buffer implementations as long as they can be viewed as a &[u8].
6 pub trait Buffer: Deref<Target = [u8]> + Sized {
7     // The `BufferString` allows for a buffer to return a custom string which will have the
8     // lifetime of the underlying buffer. A simple `std::str::from_utf8` wouldn't work since that
9     // returns a &str, which is then owned by the callee (cannot be returned from a function).
10     //
11     // Example: During deserialization a `BufferString` is returned, allowing the deserializer
12     // to "borrow" the given str - b/c there is a "lifetime" guarantee, so to speak, from the
13     // underlying buffer.
14     /// A BufferString which will live at least as long as the Buffer itself.
15     ///
16     /// Deref's to UTF-8 `str`, and only generated from the `buffer_str` function Result.
17     type BufferString: Deref<Target = str> + Sized;
18 
19     /// This method returns an instance of type Self. This allows for lifetimes to be tracked
20     /// in cases of deserialization.
21     ///
22     /// It also lets custom buffers manage reference counts.
23     ///
24     /// Returns None if:
25     /// - range start is greater than end
26     /// - range end is out of bounds
27     ///
28     /// This operation should be fast -> O(1), ideally with no heap allocations.
slice(&self, range: Range<usize>) -> Option<Self>29     fn slice(&self, range: Range<usize>) -> Option<Self>;
30 
31     /// Creates a shallow copy of the given buffer, similar to `slice`.
32     ///
33     /// This operation should be fast -> O(1), ideally with no heap allocations.
34     #[inline]
shallow_copy(&self) -> Self35     fn shallow_copy(&self) -> Self {
36         self.slice(0..self.len()).unwrap()
37     }
38 
39     /// Creates an empty instance of a `Buffer`. This is different than `Default` b/c it
40     /// guarantees that the buffer instance will have length zero.
41     ///
42     /// Most impls shold be able to implement this via `Default`.
empty() -> Self43     fn empty() -> Self;
44 
45     /// Based off of the `empty` function, allows override for optimization purposes.
46     #[inline]
empty_str() -> Self::BufferString47     fn empty_str() -> Self::BufferString {
48         Self::empty().buffer_str().unwrap()
49     }
50 
51     /// Attempts to convert the given buffer to a custom string type.
52     ///
53     /// This should fail if the type does not have valid UTF-8 bytes, and must be zero copy.
buffer_str(&self) -> Result<Self::BufferString, std::str::Utf8Error>54     fn buffer_str(&self) -> Result<Self::BufferString, std::str::Utf8Error>;
55 }
56 
57 impl<'de> Buffer for &'de [u8] {
58     type BufferString = &'de str;
59 
60     #[inline]
slice(&self, range: Range<usize>) -> Option<Self>61     fn slice(&self, range: Range<usize>) -> Option<Self> {
62         self.get(range)
63     }
64 
65     #[inline]
empty() -> Self66     fn empty() -> Self {
67         &[]
68     }
69 
70     /// Based off of the `empty` function, allows override for optimization purposes.
71     #[inline]
empty_str() -> Self::BufferString72     fn empty_str() -> Self::BufferString {
73         &""
74     }
75 
76     #[inline]
buffer_str(&self) -> Result<Self::BufferString, std::str::Utf8Error>77     fn buffer_str(&self) -> Result<Self::BufferString, std::str::Utf8Error> {
78         std::str::from_utf8(self)
79     }
80 }
81 
82