blob: 4643cb8d456e5ee0a0a370d7c6f03ea39e099d3a [file] [log] [blame]
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)
}
}