VarZeroVec

Struct VarZeroVec 

Source
pub struct VarZeroVec<'a, T: ?Sized, F = Index16>(/* private fields */);
Expand description

A zero-copy, byte-aligned 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. zerovec::make_varule may be used to generate a dynamically-sized VarULE type and conversions to and from a custom type.

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>>

Most of the methods on VarZeroVec<'a, T> come from its Deref implementation to VarZeroSlice<T>.

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.

The F type parameter is a VarZeroVecFormat (see its docs for more details), which can be used to select the precise format of the backing buffer with various size and performance tradeoffs. It defaults to Index16.

§Bytes and Equality

Two VarZeroVecs are equal if and only if their bytes are equal, as described in the trait VarULE. However, we do not guarantee stability of byte equality or serialization format across major SemVer releases.

To compare a Vec<T> to a VarZeroVec<T>, it is generally recommended to use Iterator::eq, since it is somewhat expensive at runtime to convert from a Vec<T> to a VarZeroVec<T> or vice-versa.

Prior to zerovec reaching 1.0, the precise byte representation of VarZeroVec is still under consideration, with different options along the space-time spectrum. See #1410.

§Example

use zerovec::VarZeroVec;

// The little-endian bytes correspond to the list of strings.
let strings = vec!["w", "ω", "文", "𑄃"];

#[derive(serde::Serialize, serde::Deserialize)]
struct Data<'a> {
    #[serde(borrow)]
    strings: VarZeroVec<'a, str>,
}

let data = Data {
    strings: VarZeroVec::from(&strings),
};

let bincode_bytes =
    bincode::serialize(&data).expect("Serialization should be successful");

// Will deserialize without allocations
let deserialized: Data = bincode::deserialize(&bincode_bytes)
    .expect("Deserialization should be successful");

assert_eq!(deserialized.strings.get(2), Some("文"));
assert_eq!(deserialized.strings, &*strings);

Here’s another example with ZeroSlice<T> (similar to [T]):

use zerovec::VarZeroVec;
use zerovec::ZeroSlice;

// The structured list correspond to the list of integers.
let numbers: &[&[u32]] = &[
    &[12, 25, 38],
    &[39179, 100],
    &[42, 55555],
    &[12345, 54321, 9],
];

#[derive(serde::Serialize, serde::Deserialize)]
struct Data<'a> {
    #[serde(borrow)]
    vecs: VarZeroVec<'a, ZeroSlice<u32>>,
}

let data = Data {
    vecs: VarZeroVec::from(numbers),
};

let bincode_bytes =
    bincode::serialize(&data).expect("Serialization should be successful");

let deserialized: Data = bincode::deserialize(&bincode_bytes)
    .expect("Deserialization should be successful");

assert_eq!(deserialized.vecs[0].get(1).unwrap(), 25);
assert_eq!(deserialized.vecs[1], *numbers[1]);

VarZeroVecs can be nested infinitely via a similar mechanism, see the docs of VarZeroSlice for more information.

§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:

  • 2 bytes for length (interpreted as a little-endian u16)
  • 2 * (length - 1) bytes of indices (interpreted as little-endian u16s)
  • Remaining bytes for actual data

The format is tweakable by setting the F parameter, by default it uses u16 indices and lengths but other VarZeroVecFormat types can set other sizes.

Each element in the indices array points to the ending index of its corresponding data part in the data list. The starting index can be calculated from the ending index of the next element (or 0 for the first element). The last ending index, not stored in the array, is the length of the data segment.

See the design doc for more details.

Implementations§

Source§

impl<'a, T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVec<'a, T, F>

Source

pub const fn new() -> Self

Creates a new, empty VarZeroVec<T>.

§Examples
use zerovec::VarZeroVec;

let vzv: VarZeroVec<str> = VarZeroVec::new();
assert!(vzv.is_empty());
Source

pub fn parse_bytes(slice: &'a [u8]) -> Result<Self, UleError>

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");
Source

pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self

Uses a &[u8] buffer as a VarZeroVec<T> without any verification.

§Safety

bytes need to be an output from VarZeroSlice::as_bytes().

Source

pub fn as_slice(&self) -> &VarZeroSlice<T, F>

Obtain this VarZeroVec as a VarZeroSlice

Source

pub fn is_owned(&self) -> bool

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, F>>§

Source

pub fn len(&self) -> usize

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);
Source

pub fn is_empty(&self) -> bool

Returns true if the slice contains no elements.

§Examples

let strings: Vec<String> = vec![];
let vec = VarZeroVec::<str>::from(&strings);

assert!(vec.is_empty());
Source

pub fn iter<'b>(&'b self) -> VarZeroSliceIter<'b, T, F>

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");
Source

pub fn get(&self, idx: usize) -> Option<&T>

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);
Source

pub unsafe fn get_unchecked(&self, idx: usize) -> &T

Get one of this slice’s elements

§Safety

index must be in range

§Example

let strings = vec!["foo", "bar", "baz", "quux"];
let vec = VarZeroVec::<str>::from(&strings);

let mut iter_results: Vec<&str> = vec.iter().collect();
unsafe {
    assert_eq!(vec.get_unchecked(0), "foo");
    assert_eq!(vec.get_unchecked(1), "bar");
    assert_eq!(vec.get_unchecked(2), "baz");
    assert_eq!(vec.get_unchecked(3), "quux");
}
Source

pub fn as_bytes(&self) -> &[u8]

Get a reference to the entire encoded backing buffer of this slice

The bytes can be passed back to Self::parse_bytes().

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_bytes(vzv.as_bytes()).unwrap());
Source

pub fn as_varzerovec<'a>(&'a self) -> VarZeroVec<'a, T, F>

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));
Source

pub fn binary_search_in_range( &self, x: &T, range: Range<usize>, ) -> Option<Result<usize, usize>>

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);
Source

pub fn binary_search_by( &self, predicate: impl FnMut(&T) -> Ordering, ) -> Result<usize, usize>

Binary searches a sorted VarZeroVec<T> for the given predicate. For more information, see the standard library function binary_search_by.

§Example
let strings = vec!["a", "b", "f", "g"];
let vec = VarZeroVec::<str>::from(&strings);

assert_eq!(vec.binary_search_by(|probe| probe.cmp("f")), Ok(2));
assert_eq!(vec.binary_search_by(|probe| probe.cmp("e")), Err(2));
Source

pub fn binary_search_in_range_by( &self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>

Binary searches a VarZeroVec<T> for the given predicate 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_by(|v| v.cmp("g"), 0..7),
    Some(Ok(3))
);
assert_eq!(
    vec.binary_search_in_range_by(|v| v.cmp("h"), 0..7),
    Some(Err(4))
);

// Will not look outside of the range:
assert_eq!(
    vec.binary_search_in_range_by(|v| v.cmp("g"), 0..1),
    Some(Err(1))
);
assert_eq!(
    vec.binary_search_in_range_by(|v| v.cmp("g"), 6..7),
    Some(Err(0))
);

// Will return indices relative to the start of the range:
assert_eq!(
    vec.binary_search_in_range_by(|v| v.cmp("g"), 1..6),
    Some(Ok(2))
);
assert_eq!(
    vec.binary_search_in_range_by(|v| v.cmp("h"), 1..6),
    Some(Err(3))
);

// Will return `None` if the range is out of bounds:
assert_eq!(
    vec.binary_search_in_range_by(|v| v.cmp("x"), 100..200),
    None
);
assert_eq!(vec.binary_search_in_range_by(|v| v.cmp("x"), 0..200), None);

Trait Implementations§

Source§

impl<'a, T: ?Sized, F> Clone for VarZeroVec<'a, T, F>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T, F: VarZeroVecFormat> Debug for VarZeroVec<'_, T, F>
where T: Debug + VarULE + ?Sized,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Default for VarZeroVec<'_, T, F>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Deref for VarZeroVec<'_, T, F>

Source§

type Target = VarZeroSlice<T, F>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &VarZeroSlice<T, F>

Dereferences the value.
Source§

impl<T, F> EncodeAsVarULE<VarZeroSlice<T, F>> for VarZeroVec<'_, T, F>
where T: VarULE + ?Sized, F: VarZeroVecFormat,

Source§

fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R

Calls cb with a piecewise list of byte slices that when concatenated produce the memory pattern of the corresponding instance of T. Read more
Source§

fn encode_var_ule_len(&self) -> usize

Return the length, in bytes, of the corresponding VarULE type
Source§

fn encode_var_ule_write(&self, dst: &mut [u8])

Write the corresponding VarULE type to the dst buffer. dst should be the size of Self::encode_var_ule_len()
Source§

impl<'a, T: ?Sized, F> From<&'a VarZeroSlice<T, F>> for VarZeroVec<'a, T, F>

Source§

fn from(other: &'a VarZeroSlice<T, F>) -> Self

Converts to this type from the input type.
Source§

impl<'a, T: VarULE + ?Sized + Ord, F: VarZeroVecFormat> Ord for VarZeroVec<'a, T, F>

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl<T, A, F> PartialEq<&[A]> for VarZeroVec<'_, T, F>
where T: VarULE + ?Sized + PartialEq, A: AsRef<T>, F: VarZeroVecFormat,

Source§

fn eq(&self, other: &&[A]) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T, A, F, const N: usize> PartialEq<[A; N]> for VarZeroVec<'_, T, F>
where T: VarULE + ?Sized + PartialEq, A: AsRef<T>, F: VarZeroVecFormat,

Source§

fn eq(&self, other: &[A; N]) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, 'b, T, F> PartialEq<VarZeroVec<'b, T, F>> for VarZeroVec<'a, T, F>

Source§

fn eq(&self, other: &VarZeroVec<'b, T, F>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, T: VarULE + ?Sized + PartialOrd, F: VarZeroVecFormat> PartialOrd for VarZeroVec<'a, T, F>

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<'a, T: 'static + VarULE + ?Sized> Yokeable<'a> for VarZeroVec<'static, T>

This impl requires enabling the optional yoke Cargo feature of the zerovec crate

Source§

type Output = VarZeroVec<'a, T>

This type MUST be Self with the 'static replaced with 'a, i.e. Self<'a>
Source§

fn transform(&'a self) -> &'a Self::Output

This method must cast self between &'a Self<'static> and &'a Self<'a>. Read more
Source§

fn transform_owned(self) -> Self::Output

This method must cast self between Self<'static> and Self<'a>. Read more
Source§

unsafe fn make(from: Self::Output) -> Self

This method can be used to cast away Self<'a>’s lifetime. Read more
Source§

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
Source§

impl<'zf, T, F: VarZeroVecFormat> ZeroFrom<'zf, VarZeroSlice<T, F>> for VarZeroVec<'zf, T, F>
where T: 'static + VarULE + ?Sized,

Source§

fn zero_from(other: &'zf VarZeroSlice<T, F>) -> Self

Clone the other C into a struct that may retain references into C.
Source§

impl<'zf, T, F: VarZeroVecFormat> ZeroFrom<'zf, VarZeroVec<'_, T, F>> for VarZeroVec<'zf, T, F>
where T: 'static + VarULE + ?Sized,

Source§

fn zero_from(other: &'zf VarZeroVec<'_, T, F>) -> Self

Clone the other C into a struct that may retain references into C.
Source§

impl<'a, T, F> Eq for VarZeroVec<'a, T, F>
where T: VarULE + ?Sized + Eq, F: VarZeroVecFormat,

Auto Trait Implementations§

§

impl<'a, T, F> Freeze for VarZeroVec<'a, T, F>
where T: ?Sized,

§

impl<'a, T, F> RefUnwindSafe for VarZeroVec<'a, T, F>

§

impl<'a, T, F> Send for VarZeroVec<'a, T, F>
where F: Sync, T: Sync + ?Sized,

§

impl<'a, T, F> Sync for VarZeroVec<'a, T, F>
where F: Sync, T: Sync + ?Sized,

§

impl<'a, T, F> Unpin for VarZeroVec<'a, T, F>
where T: ?Sized,

§

impl<'a, T, F> UnwindSafe for VarZeroVec<'a, T, F>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.