[Rust] Shared String (#6367)

* Adds shared strings and tests for shared strings

* Adds resets on string_map

* Moved shared strings to use vector instead of hashmap

* Addresses all the issues

* Resolves some comments
This commit is contained in:
mustiikhalil
2021-01-04 17:18:35 +03:00
committed by GitHub
parent 44cf2bde19
commit 57f68e2896
3 changed files with 92 additions and 0 deletions

View File

@@ -54,6 +54,7 @@ pub struct FlatBufferBuilder<'fbb> {
min_align: usize,
force_defaults: bool,
strings_pool: Vec<WIPOffset<&'fbb str>>,
_phantom: PhantomData<&'fbb ()>,
}
@@ -88,6 +89,7 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
min_align: 0,
force_defaults: false,
strings_pool: Vec::new(),
_phantom: PhantomData,
}
@@ -121,6 +123,7 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
self.finished = false;
self.min_align = 0;
self.strings_pool.clear();
}
/// Destroy the FlatBufferBuilder, returning its internal byte vector
@@ -235,6 +238,46 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
WIPOffset::new(o.value())
}
#[inline]
pub fn create_shared_string<'a: 'b, 'b>(&'a mut self, s: &'b str) -> WIPOffset<&'fbb str> {
self.assert_not_nested(
"create_shared_string can not be called when a table or vector is under construction",
);
// Saves a ref to owned_buf since rust doesnt like us refrencing it
// in the binary_search_by code.
let buf = &self.owned_buf;
let found = self.strings_pool.binary_search_by(|offset| {
let ptr = offset.value() as usize;
// Gets The pointer to the size of the string
let str_memory = &buf[buf.len() - ptr..];
// Gets the size of the written string from buffer
let size = u32::from_le_bytes([
str_memory[0],
str_memory[1],
str_memory[2],
str_memory[3],
]) as usize;
// Size of the string size
let string_size: usize = 4;
// Fetches actual string bytes from index of string after string size
// to the size of string plus string size
let iter = str_memory[string_size..size + string_size].iter();
// Compares bytes of fetched string and current writable string
iter.cloned().cmp(s.bytes())
});
match found {
Ok(index) => self.strings_pool[index],
Err(index) => {
let address = WIPOffset::new(self.create_byte_string(s.as_bytes()).value());
self.strings_pool.insert(index, address);
address
}
}
}
/// Create a utf8 string.
///
/// The wire format represents this as a zero-terminated byte vector.

View File

@@ -93,6 +93,8 @@ impl<T> Clone for WIPOffset<T> {
}
}
impl<T> Eq for WIPOffset<T> {}
impl<T> PartialEq for WIPOffset<T> {
fn eq(&self, o: &WIPOffset<T>) -> bool {
self.value() == o.value()