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