mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-08 22:20:56 +00:00
[rust] Genericize flexbuffer reader (#6450)
* feature/rust-tokio-bytes added feature name for tokio-bytes * Added flexbuffer implementation, TODO: typecast to avoid recurse * Converted codebase to utilize FlexBuffer implementation, need to resolve deserialization issues * Added todo for lifetime issue, may use &'de [u8] for deserializer instead of current method * Added proper &[u8] implementation * Removed unused struct * Added experimental fix to get_slice * Added experimental fix to get_slice * Avoided lifetime issues via ref structs, need to check if this hurts peformance * Updated deserializer implementation to allow for borrowed data from Reader struct * Fixed bug with str * Removed unnecessary generic parameter * Added unsafe to avoid lifetime complaints, current tests pass, need to review alternatives to unsafe * Opinionated: Removed bytes crate as this implementation could be done in a separate crate * Cleaned up flatbuffer * Fixed sample / example * Resolved PR feedback, need to resolve issues with tests * Cleaned up FlexBuffer trait to be an auto impl * Removed TODO * Reverted Deserializer to only support &'de [u8] * Cleaned up / renamed function for clarification * Renamed FlexBuffer -> InternalBuffer for clarification on it's purpose * Fixed issue with key bytes * resolved issues with broken tests, confirming this is a breaking change * Removed FIXME that's solved by splitting String and Key variants * Implemented associated types approach * Fixed backward slice logic * Fixed MapReader compile error * Added from_buffer for deserialization, removed function since it's only needed for deserialization * Removed dead code * Cleaned up buffer, removed AsRef in favor of Deref * Renamed Buffer::as_str -> Buffer::buffer_str * Minor cleanup * Updated documentation, need to fix tests * Removed unnecessary & * Removed unused lifetime * removed unnecessary as_ref * Minor optimization wrap-up * resolved issue with Clone * Added test to verify no deep-copy * Added for optimization * Updated to use empty fn instead of default * Updated comments / test name - plus the 0.3.0 version bump * comment
This commit is contained in:
81
rust/flexbuffers/src/buffer.rs
Normal file
81
rust/flexbuffers/src/buffer.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
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;
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user