| use std::ops::{Deref, Range}; | |
| /// The underlying buffer that is used by a flexbuffer Reader. | |
| /// | |
| /// This allows for custom buffer implementations as long as they can be viewed as a &[u8]. | |
| pub trait Buffer: Deref<Target = [u8]> + Sized { | |
| // The `BufferString` allows for a buffer to return a custom string which will have the | |
| // lifetime of the underlying buffer. A simple `std::str::from_utf8` wouldn't work since that | |
| // returns a &str, which is then owned by the callee (cannot be returned from a function). | |
| // | |
| // Example: During deserialization a `BufferString` is returned, allowing the deserializer | |
| // to "borrow" the given str - b/c there is a "lifetime" guarantee, so to speak, from the | |
| // underlying buffer. | |
| /// A BufferString which will live at least as long as the Buffer itself. | |
| /// | |
| /// Deref's to UTF-8 `str`, and only generated from the `buffer_str` function Result. | |
| type BufferString: Deref<Target = str> + Sized + serde::ser::Serialize; | |
| /// This method returns an instance of type Self. This allows for lifetimes to be tracked | |
| /// in cases of deserialization. | |
| /// | |
| /// It also lets custom buffers manage reference counts. | |
| /// | |
| /// Returns None if: | |
| /// - range start is greater than end | |
| /// - range end is out of bounds | |
| /// | |
| /// This operation should be fast -> O(1), ideally with no heap allocations. | |
| fn slice(&self, range: Range<usize>) -> Option<Self>; | |
| /// Creates a shallow copy of the given buffer, similar to `slice`. | |
| /// | |
| /// This operation should be fast -> O(1), ideally with no heap allocations. | |
| #[inline] | |
| fn shallow_copy(&self) -> Self { | |
| self.slice(0..self.len()).unwrap() | |
| } | |
| /// Creates an empty instance of a `Buffer`. This is different than `Default` b/c it | |
| /// guarantees that the buffer instance will have length zero. | |
| /// | |
| /// Most impls shold be able to implement this via `Default`. | |
| fn empty() -> Self; | |
| /// Based off of the `empty` function, allows override for optimization purposes. | |
| #[inline] | |
| fn empty_str() -> Self::BufferString { | |
| Self::empty().buffer_str().unwrap() | |
| } | |
| /// Attempts to convert the given buffer to a custom string type. | |
| /// | |
| /// This should fail if the type does not have valid UTF-8 bytes, and must be zero copy. | |
| fn buffer_str(&self) -> Result<Self::BufferString, std::str::Utf8Error>; | |
| } | |
| impl<'de> Buffer for &'de [u8] { | |
| type BufferString = &'de str; | |
| #[inline] | |
| fn slice(&self, range: Range<usize>) -> Option<Self> { | |
| self.get(range) | |
| } | |
| #[inline] | |
| fn empty() -> Self { | |
| &[] | |
| } | |
| /// Based off of the `empty` function, allows override for optimization purposes. | |
| #[inline] | |
| fn empty_str() -> Self::BufferString { | |
| "" | |
| } | |
| #[inline] | |
| fn buffer_str(&self) -> Result<Self::BufferString, std::str::Utf8Error> { | |
| std::str::from_utf8(self) | |
| } | |
| } |