pub enum VarZeroVec<'a, T: ?Sized, F = Index16> {
    Owned(VarZeroVecOwned<T, F>),
    Borrowed(&'a VarZeroSlice<T, F>),
}
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. 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.

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::ule::*;
use zerovec::VarZeroVec;
use zerovec::ZeroSlice;
use zerovec::ZeroVec;

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

  • 4 bytes for length (interpreted as a little-endian u32)
  • 4 * length bytes of indices (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).

See the design doc for more details.

Variants

Owned(VarZeroVecOwned<T, F>)

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

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, 1, 0, 3, 0, 6, 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");

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

Safety

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

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

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

Obtain an owned Vec<Box<T>> out of this

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

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

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

Returns a TokenStream that would evalutate to self. Read more

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

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

The resulting type after dereferencing.

Dereferences the value.

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

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

Converts to this type from the input type.

The type returned by Self::remove() and Self::replace()

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

Push an element to the end of this vector

Create a new, empty vector, with given capacity

Remove all elements from the vector

Reserve space for addl additional elements

Convert an owned value to a borrowed T

Construct from the borrowed version of the type Read more

Extract the inner borrowed variant if possible. Returns None if the data is owned. Read more

This method returns an Ordering between self and other. Read more

Compares and returns the maximum of two values. Read more

Compares and returns the minimum of two values. Read more

Restrict a value to a certain interval. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

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

This method tests less than (for self and other) and is used by the < operator. Read more

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more

This method tests greater than (for self and other) and is used by the > operator. Read more

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

This impl can be made available by enabling the optional serde feature of the zerovec crate

Serialize this value into the given Serde serializer. Read more

This impl can be made available by enabling the optional yoke feature of the zerovec crate

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

This method must cast self between &'a mut Self<'static> and &'a mut Self<'a>, and pass it to f. Read more

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

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

The type returned by Self::get()

A fully borrowed version of this

Create a new, empty borrowed variant

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

Search for a key in a sorted vector by a predicate, 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 by a predicate. 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

Get element at index

The length of this vector

Construct a borrowed variant by borrowing from &self. Read more

Obtain a reference to T, passed to a closure Read more

Check if this vector is in ascending order according to Ts Ord impl

Check if this vector is empty

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

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

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

The resulting type after obtaining ownership.

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

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

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.