Enum zerovec::varzerovec::VarZeroVec
source · [−]pub enum VarZeroVec<'a, T: ?Sized> {
Owned(VarZeroVecOwned<T>),
Borrowed(&'a VarZeroSlice<T>),
}
Expand description
A zero-copy vector for variable-width types.
VarZeroVec<T>
is designed as a drop-in replacement for Vec<T>
in situations where it is
desirable to borrow data from an unaligned byte slice, such as zero-copy deserialization, and
where T
’s data is variable-length (e.g. String
)
T
must implement VarULE
, which is already implemented for str
and [u8]
. For storing more
complicated series of elements, it is implemented on ZeroSlice<T>
as well as VarZeroSlice<T>
for nesting.
For example, here are some owned types and their zero-copy equivalents:
Vec<String>
:VarZeroVec<'a, str>
Vec<Vec<u8>>>
:VarZeroVec<'a, [u8]>
Vec<Vec<u32>>
:VarZeroVec<'a, ZeroSlice<u32>>
Vec<Vec<String>>
:VarZeroVec<'a, VarZeroSlice<str>>
For creating zero-copy vectors of fixed-size types, see ZeroVec
.
VarZeroVec<T>
behaves much like Cow
, where it can be constructed from
owned data (and then mutated!) but can also borrow from some buffer.
How it Works
VarZeroVec<T>
, when used with non-human-readable serializers (like bincode
), will
serialize to a specially formatted list of bytes. The format is:
- 4 bytes for
length
(interpreted as a little-endian u32) 4 * length
bytes ofindices
(interpreted as little-endian u32)- Remaining bytes for actual
data
Each element in the indices
array points to the starting index of its corresponding
data part in the data
list. The ending index can be calculated from the starting index
of the next element (or the length of the slice if dealing with the last element).
Safety
VarZeroVec<T>
is implemented with a fair amount of unsafe code, but is externally
safe to use.
Example
use zerovec::VarZeroVec;
// The little-endian bytes correspond to the list of strings.
let strings = vec!["w", "ω", "文", "𑄃"];
let bytes = &[
4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,
6, 0, 0, 0, 119, 207, 137, 230, 150, 135, 240, 145, 132, 131,
];
let zerovec: VarZeroVec<str> = VarZeroVec::parse_byte_slice(bytes)?;
assert_eq!(zerovec.get(2), Some("文"));
assert_eq!(zerovec, &*strings);
Here’s another example with ZeroSlice<T>
(similar to [T]
):
use zerovec::VarZeroVec;
use zerovec::ZeroVec;
use zerovec::ZeroSlice;
use zerovec::ule::*;
// The structured list correspond to the list of integers.
let numbers: Vec<Vec<u32>> = vec![
vec![12, 25, 38],
vec![39179, 100],
vec![42, 55555],
vec![12345, 54321, 9],
];
let bytes = &[4, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 20, 0, 0, 0, 28, 0, 0, 0,
12, 0, 0, 0, 25, 0, 0, 0, 38, 0, 0, 0, 11, 153, 0, 0, 100, 0,
0, 0, 42, 0, 0, 0, 3, 217, 0, 0, 57, 48, 0, 0, 49, 212, 0, 0,
9, 0, 0, 0];
let zerovec1: VarZeroVec<ZeroSlice<u32>> = VarZeroVec::parse_byte_slice(bytes)?;
assert_eq!(zerovec1.get(2).and_then(|v| v.get(1)), Some(55555));
let zerovec2: VarZeroVec<ZeroSlice<u32>> = (&numbers).into();
assert_eq!(zerovec1, zerovec2);
VarZeroVec
s can be nested infinitely, see the docs of VarZeroSlice
for more information.
Variants
Owned(VarZeroVecOwned<T>)
An allocated VarZeroVec, allowing for mutations.
Examples
use zerovec::VarZeroVec;
let mut vzv = VarZeroVec::<str>::default();
vzv.make_mut().push("foo");
vzv.make_mut().push("bar");
assert!(matches!(vzv, VarZeroVec::Owned(_)));
Borrowed(&'a VarZeroSlice<T>)
A borrowed VarZeroVec, requiring no allocations.
If a mutating operation is invoked on VarZeroVec, the Borrowed is converted to Owned.
Examples
use zerovec::VarZeroVec;
let bytes = &[
4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,
6, 0, 0, 0, 119, 207, 137, 230, 150, 135, 240, 145, 132, 131,
];
let vzv: VarZeroVec<str> = VarZeroVec::parse_byte_slice(bytes).unwrap();
assert!(matches!(vzv, VarZeroVec::Borrowed(_)));
Implementations
Creates a new, empty VarZeroVec<T>
.
Examples
use zerovec::VarZeroVec;
let vzv: VarZeroVec<str> = VarZeroVec::new();
assert!(vzv.is_empty());
Parse a VarZeroVec from a slice of the appropriate format
Slices of the right format can be obtained via VarZeroSlice::as_bytes()
.
Example
let strings = vec!["foo", "bar", "baz", "quux"];
let vec = VarZeroVec::<str>::from(&strings);
assert_eq!(&vec[0], "foo");
assert_eq!(&vec[1], "bar");
assert_eq!(&vec[2], "baz");
assert_eq!(&vec[3], "quux");
Convert this into a mutable vector of the owned T
type, cloning if necessary.
Example
let strings = vec!["foo", "bar", "baz", "quux"];
let mut vec = VarZeroVec::<str>::from(&strings);
assert_eq!(vec.len(), 4);
let mutvec = vec.make_mut();
mutvec.push("lorem ipsum".into());
mutvec[2] = "dolor sit".into();
assert_eq!(&vec[0], "foo");
assert_eq!(&vec[1], "bar");
assert_eq!(&vec[2], "dolor sit");
assert_eq!(&vec[3], "quux");
assert_eq!(&vec[4], "lorem ipsum");
Converts a borrowed ZeroVec to an owned ZeroVec. No-op if already owned.
Example
let strings = vec!["foo", "bar", "baz", "quux"];
let vec = VarZeroVec::<str>::from(&strings);
assert_eq!(vec.len(), 4);
// has 'static lifetime
let owned = vec.into_owned();
Obtain this VarZeroVec
as a VarZeroSlice
Takes the byte vector representing the encoded data of this VarZeroVec. If borrowed, this function allocates a byte vector and copies the borrowed bytes into it.
The bytes can be passed back to Self::parse_byte_slice()
.
To get a reference to the bytes without moving, see VarZeroSlice::as_bytes()
.
Example
let strings = vec!["foo", "bar", "baz"];
let bytes = VarZeroVec::<str>::from(&strings).into_bytes();
let mut borrowed: VarZeroVec<str> = VarZeroVec::parse_byte_slice(&bytes)?;
assert_eq!(borrowed, &*strings);
Return whether the VarZeroVec
is operating on owned or borrowed
data. VarZeroVec::into_owned()
and VarZeroVec::make_mut()
can
be used to force it into an owned type
Methods from Deref<Target = VarZeroSlice<T>>
Get the number of elements in this slice
Example
let strings = vec!["foo", "bar", "baz", "quux"];
let vec = VarZeroVec::<str>::from(&strings);
assert_eq!(vec.len(), 4);
Returns true
if the slice contains no elements.
Examples
let strings: Vec<String> = vec![];
let vec = VarZeroVec::<str>::from(&strings);
assert!(vec.is_empty());
Obtain an iterator over this slice’s elements
Example
let strings = vec!["foo", "bar", "baz", "quux"];
let vec = VarZeroVec::<str>::from(&strings);
let mut iter_results: Vec<&str> = vec.iter().collect();
assert_eq!(iter_results[0], "foo");
assert_eq!(iter_results[1], "bar");
assert_eq!(iter_results[2], "baz");
assert_eq!(iter_results[3], "quux");
Get one of this slice’s elements, returning None if the index is out of bounds
Example
let strings = vec!["foo", "bar", "baz", "quux"];
let vec = VarZeroVec::<str>::from(&strings);
let mut iter_results: Vec<&str> = vec.iter().collect();
assert_eq!(vec.get(0), Some("foo"));
assert_eq!(vec.get(1), Some("bar"));
assert_eq!(vec.get(2), Some("baz"));
assert_eq!(vec.get(3), Some("quux"));
assert_eq!(vec.get(4), None);
Get a reference to the entire encoded backing buffer of this slice
The bytes can be passed back to Self::parse_byte_slice()
.
To take the bytes as a vector, see VarZeroVec::into_bytes()
.
Example
let strings = vec!["foo", "bar", "baz"];
let vzv = VarZeroVec::<str>::from(&strings);
assert_eq!(vzv, VarZeroVec::parse_byte_slice(vzv.as_bytes()).unwrap());
Get this VarZeroSlice
as a borrowed VarZeroVec
If you wish to repeatedly call methods on this VarZeroSlice
,
it is more efficient to perform this conversion first
Binary searches a sorted VarZeroVec<T>
for the given element. For more information, see
the standard library function binary_search
.
Example
let strings = vec!["a", "b", "f", "g"];
let vec = VarZeroVec::<str>::from(&strings);
assert_eq!(vec.binary_search("f"), Ok(2));
assert_eq!(vec.binary_search("e"), Err(2));
Binary searches a VarZeroVec<T>
for the given element within a certain sorted range.
If the range is out of bounds, returns None
. Otherwise, returns a Result
according
to the behavior of the standard library function binary_search
.
The index is returned relative to the start of the range.
Example
let strings = vec!["a", "b", "f", "g", "m", "n", "q"];
let vec = VarZeroVec::<str>::from(&strings);
// Same behavior as binary_search when the range covers the whole slice:
assert_eq!(vec.binary_search_in_range("g", 0..7), Some(Ok(3)));
assert_eq!(vec.binary_search_in_range("h", 0..7), Some(Err(4)));
// Will not look outside of the range:
assert_eq!(vec.binary_search_in_range("g", 0..1), Some(Err(1)));
assert_eq!(vec.binary_search_in_range("g", 6..7), Some(Err(0)));
// Will return indices relative to the start of the range:
assert_eq!(vec.binary_search_in_range("g", 1..6), Some(Ok(2)));
assert_eq!(vec.binary_search_in_range("h", 1..6), Some(Err(3)));
// Will return None if the range is out of bounds:
assert_eq!(vec.binary_search_in_range("x", 100..200), None);
assert_eq!(vec.binary_search_in_range("x", 0..200), None);
Trait Implementations
type Target = VarZeroSlice<T>
type Target = VarZeroSlice<T>
The resulting type after dereferencing.
Dereferences the value.
impl<'de, 'a, T> Deserialize<'de> for VarZeroVec<'a, T> where
T: VarULE + ?Sized,
Box<T>: Deserialize<'de>,
'de: 'a,
impl<'de, 'a, T> Deserialize<'de> for VarZeroVec<'a, T> where
T: VarULE + ?Sized,
Box<T>: Deserialize<'de>,
'de: 'a,
This impl can be made available by enabling the optional serde
feature of the zerovec
crate
Deserialize this value from the given Serde deserializer. Read more
Calls cb
with a piecewise list of byte slices that when concatenated
produce the memory pattern of the corresponding instance of T
. Read more
Return the length, in bytes, of the corresponding VarULE
type
Write the corresponding VarULE
type to the dst
buffer. dst
should
be the size of Self::encode_var_ule_len()
Read more
impl<A, T, const N: usize> From<&'_ [A; N]> for VarZeroVec<'static, T> where
T: VarULE + ?Sized,
A: EncodeAsVarULE<T>,
impl<A, T, const N: usize> From<&'_ [A; N]> for VarZeroVec<'static, T> where
T: VarULE + ?Sized,
A: EncodeAsVarULE<T>,
impl<A, T> From<&'_ [A]> for VarZeroVec<'static, T> where
T: VarULE + ?Sized,
A: EncodeAsVarULE<T>,
impl<A, T> From<&'_ [A]> for VarZeroVec<'static, T> where
T: VarULE + ?Sized,
A: EncodeAsVarULE<T>,
impl<A, T> From<&'_ Vec<A, Global>> for VarZeroVec<'static, T> where
T: VarULE + ?Sized,
A: EncodeAsVarULE<T>,
impl<A, T> From<&'_ Vec<A, Global>> for VarZeroVec<'static, T> where
T: VarULE + ?Sized,
A: EncodeAsVarULE<T>,
Performs the conversion.
Performs the conversion.
Performs the conversion.
impl<'a, T> MutableZeroVecLike<'a, T> for VarZeroVec<'a, T> where
T: VarULE,
T: Ord,
T: ?Sized,
impl<'a, T> MutableZeroVecLike<'a, T> for VarZeroVec<'a, T> where
T: VarULE,
T: Ord,
T: ?Sized,
Insert an element at index
Remove the element at index
(panicking if nonexistant)
Replace the element at index
with another one, returning the old element
Create a new, empty vector, with given capacity
Reserve space for addl
additional elements
Convert an owned value to a borrowed T
impl<'a, 'b, T> PartialEq<VarZeroVec<'b, T>> for VarZeroVec<'a, T> where
T: VarULE,
T: ?Sized,
T: PartialEq,
impl<'a, 'b, T> PartialEq<VarZeroVec<'b, T>> for VarZeroVec<'a, T> where
T: VarULE,
T: ?Sized,
T: PartialEq,
This impl can be made available by enabling the optional serde
feature of the zerovec
crate
This impl can be made available by enabling the optional yoke
feature of the zerovec
crate
type Output = VarZeroVec<'a, T>
type Output = VarZeroVec<'a, T>
This type MUST be Self
with the 'static
replaced with 'a
, i.e. Self<'a>
This method must cast self
between &'a Self<'static>
and &'a Self<'a>
. Read more
This method must cast self
between Self<'static>
and Self<'a>
. Read more
This method can be used to cast away Self<'a>
’s lifetime. Read more
fn transform_mut<F>(&'a mut self, f: F) where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
fn transform_mut<F>(&'a mut self, f: F) where
F: 'static + for<'b> FnOnce(&'b mut Self::Output),
This method must cast self
between &'a mut Self<'static>
and &'a mut Self<'a>
,
and pass it to f
. Read more
impl<'zcf, T> ZeroCopyFrom<'zcf, VarZeroVec<'_, T>> for VarZeroVec<'zcf, T> where
T: 'static + VarULE + ?Sized,
impl<'zcf, T> ZeroCopyFrom<'zcf, VarZeroVec<'_, T>> for VarZeroVec<'zcf, T> where
T: 'static + VarULE + ?Sized,
Clone the cart C
into a struct that may retain references into C
.
type GetType = T
type GetType = T
The type returned by Self::get()
type BorrowedVariant = &'a VarZeroSlice<T>
type BorrowedVariant = &'a VarZeroSlice<T>
A fully borrowed version of this
Search for a key in a sorted vector, returns Ok(index)
if found,
returns Err(insert_index)
if not found, where insert_index
is the
index where it should be inserted to maintain sort order. Read more
Search for a key within a certain range in a sorted vector. Returns None
if the
range is out of bounds, and Ok
or Err
in the same way as zvl_binary_search
.
Indices are returned relative to the start of the range. Read more
Check if this vector is in ascending order according to T
s Ord
impl
Construct a borrowed variant by borrowing from &self
. Read more
Extract the inner borrowed variant if possible. Returns None
if the data is owned. Read more
Construct from the borrowed version of the type Read more
Compare this type with a Self::GetType
. This must produce the same result as
if g
were converted to Self
Read more
Compare two values of Self::GetType
. This must produce the same result as
if both a
and b
were converted to Self
Read more
Obtain a version of T suitable for serialization Read more
Check if this vector is empty
Auto Trait Implementations
impl<'a, T: ?Sized> RefUnwindSafe for VarZeroVec<'a, T> where
T: RefUnwindSafe,
impl<'a, T: ?Sized> Send for VarZeroVec<'a, T> where
T: Send + Sync,
impl<'a, T: ?Sized> Sync for VarZeroVec<'a, T> where
T: Sync,
impl<'a, T: ?Sized> Unpin for VarZeroVec<'a, T>
impl<'a, T: ?Sized> UnwindSafe for VarZeroVec<'a, T> where
T: UnwindSafe + RefUnwindSafe,
Blanket Implementations
Mutably borrows from an owned value. Read more