Struct VarZeroSlice

struct VarZeroSlice<T: ?Sized, F = Index16> { ... }

A zero-copy "slice", that works for unsized types, i.e. the zero-copy version of [T] where T is not Sized.

This behaves similarly to [VarZeroVec<T>], however [VarZeroVec<T>] is allowed to contain owned data and as such is ideal for deserialization since most human readable serialization formats cannot unconditionally deserialize zero-copy.

This type can be used inside VarZeroVec<T> and ZeroMap: This essentially allows for the construction of zero-copy types isomorphic to Vec<Vec<T>> by instead using VarZeroVec<ZeroSlice<T>>.

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.

This type can be nested within itself to allow for multi-level nested Vecs.

Examples

Nested Slices

The following code constructs the conceptual zero-copy equivalent of Vec<Vec<Vec<str>>>

use zerovec::{VarZeroSlice, VarZeroVec};
let strings_1: Vec<&str> = vec!["foo", "bar", "baz"];
let strings_2: Vec<&str> = vec!["twelve", "seventeen", "forty two"];
let strings_3: Vec<&str> = vec!["", "喜歡", "烏龍茶"];
let strings_4: Vec<&str> = vec!["w", "ω", "", "𑄃"];
let strings_12 = vec![&*strings_1, &*strings_2];
let strings_34 = vec![&*strings_3, &*strings_4];
let all_strings = vec![strings_12, strings_34];

let vzv_1: VarZeroVec<str> = VarZeroVec::from(&strings_1);
let vzv_2: VarZeroVec<str> = VarZeroVec::from(&strings_2);
let vzv_3: VarZeroVec<str> = VarZeroVec::from(&strings_3);
let vzv_4: VarZeroVec<str> = VarZeroVec::from(&strings_4);
let vzv_12 = VarZeroVec::from(&[vzv_1.as_slice(), vzv_2.as_slice()]);
let vzv_34 = VarZeroVec::from(&[vzv_3.as_slice(), vzv_4.as_slice()]);
let vzv_all = VarZeroVec::from(&[vzv_12.as_slice(), vzv_34.as_slice()]);

let reconstructed: Vec<Vec<Vec<String>>> = vzv_all
    .iter()
    .map(|v: &VarZeroSlice<VarZeroSlice<str>>| {
        v.iter()
            .map(|x: &VarZeroSlice<_>| {
                x.as_varzerovec()
                    .iter()
                    .map(|s| s.to_owned())
                    .collect::<Vec<String>>()
            })
            .collect::<Vec<_>>()
    })
    .collect::<Vec<_>>();
assert_eq!(reconstructed, all_strings);

let bytes = vzv_all.as_bytes();
let vzv_from_bytes: VarZeroVec<VarZeroSlice<VarZeroSlice<str>>> =
    VarZeroVec::parse_bytes(bytes).unwrap();
assert_eq!(vzv_from_bytes, vzv_all);

Iterate over Windows

Although VarZeroSlice does not itself have a .windows iterator like [core::slice::Windows], this behavior can be easily modeled using an iterator:

use zerovec::VarZeroVec;

let vzv = VarZeroVec::<str>::from(&["a", "b", "c", "d"]);
# let mut pairs: Vec<(&str, &str)> = Vec::new();

let mut it = vzv.iter().peekable();
while let (Some(x), Some(y)) = (it.next(), it.peek()) {
    // Evaluate (x, y) here.
#   pairs.push((x, y));
}
# assert_eq!(pairs, &[("a", "b"), ("b", "c"), ("c", "d")]);

Implementations

impl<T, F> VarZeroSlice<T, F>

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

Example

# use zerovec::VarZeroVec;

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));
fn binary_search_in_range(self: &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

# use zerovec::VarZeroVec;
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);

impl<T, F> VarZeroSlice<T, F>

fn binary_search_by<impl FnMut(&T) -> Ordering: FnMut(&T) -> Ordering>(self: &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

# use zerovec::VarZeroVec;
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));
fn binary_search_in_range_by<impl FnMut(&T) -> Ordering: FnMut(&T) -> Ordering>(self: &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

# use zerovec::VarZeroVec;
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);

impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroSlice<T, F>

const fn new_empty() -> &'static Self

Construct a new empty VarZeroSlice

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

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

Safety

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

fn len(self: &Self) -> usize

Get the number of elements in this slice

Example

# use zerovec::VarZeroVec;

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

assert_eq!(vec.len(), 4);
fn is_empty(self: &Self) -> bool

Returns true if the slice contains no elements.

Examples

# use zerovec::VarZeroVec;

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

assert!(vec.is_empty());
fn iter<'b>(self: &'b Self) -> VarZeroSliceIter<'b, T, F>

Obtain an iterator over this slice's elements

Example

# use zerovec::VarZeroVec;

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");
fn get(self: &Self, idx: usize) -> Option<&T>

Get one of this slice's elements, returning None if the index is out of bounds

Example

# use zerovec::VarZeroVec;

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);
unsafe fn get_unchecked(self: &Self, idx: usize) -> &T

Get one of this slice's elements

Safety

index must be in range

Example

# use zerovec::VarZeroVec;

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");
}
fn to_vec(self: &Self) -> Vec<Box<T>>

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

const fn as_bytes(self: &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

# use zerovec::VarZeroVec;

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

assert_eq!(vzv, VarZeroVec::parse_bytes(vzv.as_bytes()).unwrap());
const fn as_varzerovec<'a>(self: &'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

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

Parse a VarZeroSlice from a slice of the appropriate format

Slices of the right format can be obtained via [VarZeroSlice::as_bytes()]

impl<T> Any for VarZeroSlice<T, F>

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for VarZeroSlice<T, F>

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for VarZeroSlice<T, F>

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

impl<T> EncodeAsVarULE for VarZeroSlice<T, F>

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

impl<T, F = Index16> Sized for VarZeroSlice<T, F>

impl<T, F> Eq for VarZeroSlice<T, F>

impl<T, F> Freeze for VarZeroSlice<T, F>

impl<T, F> PartialEq for VarZeroSlice<T, F>

fn eq(self: &Self, other: &VarZeroSlice<T, F>) -> bool

impl<T, F> RefUnwindSafe for VarZeroSlice<T, F>

impl<T, F> Send for VarZeroSlice<T, F>

impl<T, F> Sync for VarZeroSlice<T, F>

impl<T, F> Unpin for VarZeroSlice<T, F>

impl<T, F> UnsafeUnpin for VarZeroSlice<T, F>

impl<T, F> UnwindSafe for VarZeroSlice<T, F>

impl<T, F> ZeroVecLike for VarZeroSlice<T, F>

fn zvl_new_borrowed() -> &'static <Self as >::SliceVariant
fn zvl_binary_search_in_range(self: &Self, k: &T, range: Range<usize>) -> Option<Result<usize, usize>>
where
    T: Ord
fn zvl_binary_search_by<impl FnMut(&T) -> Ordering: FnMut(&T) -> Ordering>(self: &Self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize>
fn zvl_binary_search_in_range_by<impl FnMut(&T) -> Ordering: FnMut(&T) -> Ordering>(self: &Self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>) -> Option<Result<usize, usize>>
fn zvl_get(self: &Self, index: usize) -> Option<&T>
fn zvl_len(self: &Self) -> usize
fn zvl_as_borrowed(self: &Self) -> &VarZeroSlice<T, F>
fn zvl_get_as_t<R, impl FnOnce(&T) -> R: FnOnce(&T) -> R>(g: &<Self as >::GetType, f: impl FnOnce(&T) -> R) -> R

impl<T, F: VarZeroVecFormat> Debug for VarZeroSlice<T, F>

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

impl<T: ?Sized, F: VarZeroVecFormat> AsRef for VarZeroSlice<T, F>

fn as_ref(self: &Self) -> &VarZeroSlice<T, F>

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

fn validate_bytes(bytes: &[u8]) -> Result<(), UleError>
unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self
fn as_bytes(self: &Self) -> &[u8]

impl<T: VarULE + ?Sized + Ord, F: VarZeroVecFormat> Ord for VarZeroSlice<T, F>

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

impl<T: VarULE + ?Sized + PartialOrd, F: VarZeroVecFormat> PartialOrd for VarZeroSlice<T, F>

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

impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Index for VarZeroSlice<T, F>

fn index(self: &Self, index: usize) -> &<Self as >::Output