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 + 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 + 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) -> Option; /// 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; } impl<'de> Buffer for &'de [u8] { type BufferString = &'de str; #[inline] fn slice(&self, range: Range) -> Option { 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 { std::str::from_utf8(self) } }