pub struct ZeroVec<'a, T>where
T: AsULE,{ /* private fields */ }
Expand description
A zero-copy, byte-aligned vector for fixed-width types.
ZeroVec<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.
T
must implement AsULE
, which is auto-implemented for a number of built-in types,
including all fixed-width multibyte integers. For variable-width types like str
,
see VarZeroVec
. zerovec::make_ule
may
be used to automatically implement AsULE
for a type and generate the underlying ULE
type.
Typically, the zero-copy equivalent of a Vec<T>
will simply be ZeroVec<'a, T>
.
Most of the methods on ZeroVec<'a, T>
come from its Deref
implementation to ZeroSlice<T>
.
For creating zero-copy vectors of fixed-size types, see VarZeroVec
.
ZeroVec<T>
behaves much like Cow
, where it can be constructed from
owned data (and then mutated!) but can also borrow from some buffer.
§Example
use zerovec::ZeroVec;
// The little-endian bytes correspond to the numbers on the following line.
let nums: &[u16] = &[211, 281, 421, 461];
#[derive(serde::Serialize, serde::Deserialize)]
struct Data<'a> {
#[serde(borrow)]
nums: ZeroVec<'a, u16>,
}
// The owned version will allocate
let data = Data {
nums: ZeroVec::alloc_from_slice(nums),
};
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");
// This deserializes without allocation!
assert!(!deserialized.nums.is_owned());
assert_eq!(deserialized.nums.get(2), Some(421));
assert_eq!(deserialized.nums, nums);
§How it Works
ZeroVec<T>
represents a slice of T
as a slice of T::ULE
. The difference between T
and
T::ULE
is that T::ULE
must be encoded in little-endian with 1-byte alignment. When accessing
items from ZeroVec<T>
, we fetch the T::ULE
, convert it on the fly to T
, and return T
by
value.
Benchmarks can be found in the project repository, with some results found in the crate-level documentation.
See the design doc for more details.
Implementations§
Source§impl<'a, T: AsULE> ZeroVec<'a, T>
impl<'a, T: AsULE> ZeroVec<'a, T>
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Creates a new, borrowed, empty ZeroVec<T>
.
§Examples
use zerovec::ZeroVec;
let zv: ZeroVec<u16> = ZeroVec::new();
assert!(zv.is_empty());
Sourcepub const fn const_len(&self) -> usize
pub const fn const_len(&self) -> usize
Same as ZeroSlice::len
, which is available through Deref
and not const
.
Sourcepub fn new_owned(vec: Vec<T::ULE>) -> Self
pub fn new_owned(vec: Vec<T::ULE>) -> Self
Creates a new owned ZeroVec
using an existing
allocated backing buffer
If you have a slice of &[T]
s, prefer using
Self::alloc_from_slice()
.
Sourcepub const fn new_borrowed(slice: &'a [T::ULE]) -> Self
pub const fn new_borrowed(slice: &'a [T::ULE]) -> Self
Creates a new borrowed ZeroVec
using an existing
backing buffer
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Creates a new, owned, empty ZeroVec<T>
, with a certain capacity pre-allocated.
Sourcepub fn parse_bytes(bytes: &'a [u8]) -> Result<Self, UleError>
pub fn parse_bytes(bytes: &'a [u8]) -> Result<Self, UleError>
Parses a &[u8]
buffer into a ZeroVec<T>
.
This function is infallible for built-in integer types, but fallible for other types,
such as char
. For more information, see ULE::parse_bytes_to_slice
.
The bytes within the byte buffer must remain constant for the life of the ZeroVec.
§Endianness
The byte buffer must be encoded in little-endian, even if running in a big-endian environment. This ensures a consistent representation of data across platforms.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert!(!zerovec.is_owned());
assert_eq!(zerovec.get(2), Some(421));
Sourcepub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self
pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self
Uses a &[u8]
buffer as a ZeroVec<T>
without any verification.
§Safety
bytes
need to be an output from ZeroSlice::as_bytes()
.
Sourcepub fn into_bytes(self) -> ZeroVec<'a, u8>
pub fn into_bytes(self) -> ZeroVec<'a, u8>
Converts a ZeroVec<T>
into a ZeroVec<u8>
, retaining the current ownership model.
Note that the length of the ZeroVec may change.
§Examples
Convert a borrowed ZeroVec
:
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
let zv_bytes = zerovec.into_bytes();
assert!(!zv_bytes.is_owned());
assert_eq!(zv_bytes.get(0), Some(0xD3));
Convert an owned ZeroVec
:
use zerovec::ZeroVec;
let nums: &[u16] = &[211, 281, 421, 461];
let zerovec = ZeroVec::alloc_from_slice(nums);
let zv_bytes = zerovec.into_bytes();
assert!(zv_bytes.is_owned());
assert_eq!(zv_bytes.get(0), Some(0xD3));
Sourcepub const fn as_slice(&self) -> &ZeroSlice<T>
pub const fn as_slice(&self) -> &ZeroSlice<T>
Returns this ZeroVec
as a ZeroSlice
.
To get a reference with a longer lifetime from a borrowed ZeroVec
,
use ZeroVec::as_maybe_borrowed
.
Sourcepub fn cast<P>(self) -> ZeroVec<'a, P>
pub fn cast<P>(self) -> ZeroVec<'a, P>
Casts a ZeroVec<T>
to a compatible ZeroVec<P>
.
T
and P
are compatible if they have the same ULE
representation.
If the ULE
s of T
and P
are different types but have the same size,
use Self::try_into_converted()
.
§Examples
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec_u16: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(zerovec_u16.get(3), Some(32973));
let zerovec_i16: ZeroVec<i16> = zerovec_u16.cast();
assert_eq!(zerovec_i16.get(3), Some(-32563));
Sourcepub fn try_into_converted<P: AsULE>(self) -> Result<ZeroVec<'a, P>, UleError>
pub fn try_into_converted<P: AsULE>(self) -> Result<ZeroVec<'a, P>, UleError>
Converts a ZeroVec<T>
into a ZeroVec<P>
, retaining the current ownership model.
If T
and P
have the exact same ULE
, use Self::cast()
.
§Panics
Panics if T::ULE
and P::ULE
are not the same size.
§Examples
Convert a borrowed ZeroVec
:
use zerovec::ZeroVec;
let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
let zv_char: ZeroVec<char> =
ZeroVec::parse_bytes(bytes).expect("valid code points");
let zv_u8_3: ZeroVec<[u8; 3]> =
zv_char.try_into_converted().expect("infallible conversion");
assert!(!zv_u8_3.is_owned());
assert_eq!(zv_u8_3.get(0), Some([0x7F, 0xF3, 0x01]));
Convert an owned ZeroVec
:
use zerovec::ZeroVec;
let chars: &[char] = &['🍿', '🙉'];
let zv_char = ZeroVec::alloc_from_slice(chars);
let zv_u8_3: ZeroVec<[u8; 3]> =
zv_char.try_into_converted().expect("length is divisible");
assert!(zv_u8_3.is_owned());
assert_eq!(zv_u8_3.get(0), Some([0x7F, 0xF3, 0x01]));
If the types are not the same size, we refuse to convert:
use zerovec::ZeroVec;
let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
let zv_char: ZeroVec<char> =
ZeroVec::parse_bytes(bytes).expect("valid code points");
// Panics! core::mem::size_of::<char::ULE> != core::mem::size_of::<u16::ULE>
zv_char.try_into_converted::<u16>();
Instead, convert to bytes and then parse:
use zerovec::ZeroVec;
let bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x49, 0xF6, 0x01];
let zv_char: ZeroVec<char> =
ZeroVec::parse_bytes(bytes).expect("valid code points");
let zv_u16: ZeroVec<u16> =
zv_char.into_bytes().try_into_parsed().expect("infallible");
assert!(!zv_u16.is_owned());
assert_eq!(zv_u16.get(0), Some(0xF37F));
Sourcepub fn as_maybe_borrowed(&self) -> Option<&'a ZeroSlice<T>>
pub fn as_maybe_borrowed(&self) -> Option<&'a ZeroSlice<T>>
If this is a borrowed ZeroVec
, return it as a slice that covers
its lifetime parameter.
To infallibly get a ZeroSlice
with a shorter lifetime, use
ZeroVec::as_slice
.
Sourcepub fn owned_capacity(&self) -> Option<NonZeroUsize>
pub fn owned_capacity(&self) -> Option<NonZeroUsize>
If the ZeroVec is owned, returns the capacity of the vector.
Otherwise, if the ZeroVec is borrowed, returns None
.
§Examples
use zerovec::ZeroVec;
let mut zv = ZeroVec::<u8>::new_borrowed(&[0, 1, 2, 3]);
assert!(!zv.is_owned());
assert_eq!(zv.owned_capacity(), None);
// Convert to owned without appending anything
zv.with_mut(|v| ());
assert!(zv.is_owned());
assert_eq!(zv.owned_capacity(), Some(4.try_into().unwrap()));
// Double the size by appending
zv.with_mut(|v| v.push(0));
assert!(zv.is_owned());
assert_eq!(zv.owned_capacity(), Some(8.try_into().unwrap()));
Source§impl<'a> ZeroVec<'a, u8>
impl<'a> ZeroVec<'a, u8>
Sourcepub fn try_into_parsed<T: AsULE>(self) -> Result<ZeroVec<'a, T>, UleError>
pub fn try_into_parsed<T: AsULE>(self) -> Result<ZeroVec<'a, T>, UleError>
Converts a ZeroVec<u8>
into a ZeroVec<T>
, retaining the current ownership model.
Note that the length of the ZeroVec may change.
§Examples
Convert a borrowed ZeroVec
:
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zv_bytes = ZeroVec::new_borrowed(bytes);
let zerovec: ZeroVec<u16> = zv_bytes.try_into_parsed().expect("infallible");
assert!(!zerovec.is_owned());
assert_eq!(zerovec.get(0), Some(211));
Convert an owned ZeroVec
:
use zerovec::ZeroVec;
let bytes: Vec<u8> = vec![0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zv_bytes = ZeroVec::new_owned(bytes);
let zerovec: ZeroVec<u16> = zv_bytes.try_into_parsed().expect("infallible");
assert!(zerovec.is_owned());
assert_eq!(zerovec.get(0), Some(211));
Source§impl<'a, T> ZeroVec<'a, T>where
T: AsULE,
impl<'a, T> ZeroVec<'a, T>where
T: AsULE,
Sourcepub fn alloc_from_slice(other: &[T]) -> Self
pub fn alloc_from_slice(other: &[T]) -> Self
Creates a ZeroVec<T>
from a &[T]
by allocating memory.
This function results in an Owned
instance of ZeroVec<T>
.
§Example
use zerovec::ZeroVec;
// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];
let zerovec = ZeroVec::alloc_from_slice(nums);
assert!(zerovec.is_owned());
assert_eq!(bytes, zerovec.as_bytes());
Source§impl<'a, T> ZeroVec<'a, T>where
T: EqULE,
impl<'a, T> ZeroVec<'a, T>where
T: EqULE,
Sourcepub fn try_from_slice(slice: &'a [T]) -> Option<Self>
pub fn try_from_slice(slice: &'a [T]) -> Option<Self>
Attempts to create a ZeroVec<'a, T>
from a &'a [T]
by borrowing the argument.
If this is not possible, such as on a big-endian platform, None
is returned.
§Example
use zerovec::ZeroVec;
// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];
if let Some(zerovec) = ZeroVec::try_from_slice(nums) {
assert!(!zerovec.is_owned());
assert_eq!(bytes, zerovec.as_bytes());
}
Sourcepub fn from_slice_or_alloc(slice: &'a [T]) -> Self
pub fn from_slice_or_alloc(slice: &'a [T]) -> Self
Creates a ZeroVec<'a, T>
from a &'a [T]
, either by borrowing the argument or by
allocating a new vector.
This is a cheap operation on little-endian platforms, falling back to a more expensive operation on big-endian platforms.
§Example
use zerovec::ZeroVec;
// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let nums: &[u16] = &[211, 281, 421, 461];
let zerovec = ZeroVec::from_slice_or_alloc(nums);
// Note: zerovec could be either borrowed or owned.
assert_eq!(bytes, zerovec.as_bytes());
Source§impl<'a, T> ZeroVec<'a, T>where
T: AsULE,
impl<'a, T> ZeroVec<'a, T>where
T: AsULE,
Sourcepub fn for_each_mut(&mut self, f: impl FnMut(&mut T))
pub fn for_each_mut(&mut self, f: impl FnMut(&mut T))
Mutates each element according to a given function, meant to be
a more convenient version of calling .iter_mut()
with
ZeroVec::with_mut()
which serves fewer use cases.
This will convert the ZeroVec into an owned ZeroVec if not already the case.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
zerovec.for_each_mut(|item| *item += 1);
assert_eq!(zerovec.to_vec(), &[212, 282, 422, 462]);
assert!(zerovec.is_owned());
Sourcepub fn try_for_each_mut<E>(
&mut self,
f: impl FnMut(&mut T) -> Result<(), E>,
) -> Result<(), E>
pub fn try_for_each_mut<E>( &mut self, f: impl FnMut(&mut T) -> Result<(), E>, ) -> Result<(), E>
Same as ZeroVec::for_each_mut()
, but bubbles up errors.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
zerovec.try_for_each_mut(|item| {
*item = item.checked_add(1).ok_or(())?;
Ok(())
})?;
assert_eq!(zerovec.to_vec(), &[212, 282, 422, 462]);
assert!(zerovec.is_owned());
Sourcepub fn into_owned(self) -> ZeroVec<'static, T>
pub fn into_owned(self) -> ZeroVec<'static, T>
Converts a borrowed ZeroVec to an owned ZeroVec. No-op if already owned.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert!(!zerovec.is_owned());
let owned = zerovec.into_owned();
assert!(owned.is_owned());
Sourcepub fn with_mut<R>(&mut self, f: impl FnOnce(&mut Vec<T::ULE>) -> R) -> R
pub fn with_mut<R>(&mut self, f: impl FnOnce(&mut Vec<T::ULE>) -> R) -> R
Allows the ZeroVec to be mutated by converting it to an owned variant, and producing
a mutable vector of ULEs. If you only need a mutable slice, consider using Self::to_mut_slice()
instead.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert!(!zerovec.is_owned());
zerovec.with_mut(|v| v.push(12_u16.to_unaligned()));
assert!(zerovec.is_owned());
Sourcepub fn to_mut_slice(&mut self) -> &mut [T::ULE]
pub fn to_mut_slice(&mut self) -> &mut [T::ULE]
Allows the ZeroVec to be mutated by converting it to an owned variant (if necessary)
and returning a slice to its backing buffer. Self::with_mut()
allows for mutation
of the vector itself.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert!(!zerovec.is_owned());
zerovec.to_mut_slice()[1] = 5u16.to_unaligned();
assert!(zerovec.is_owned());
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Remove all elements from this ZeroVec and reset it to an empty borrowed state.
Sourcepub fn take_first(&mut self) -> Option<T>
pub fn take_first(&mut self) -> Option<T>
Removes the first element of the ZeroVec. The ZeroVec remains in the same borrowed or owned state.
§Examples
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert!(!zerovec.is_owned());
let first = zerovec.take_first().unwrap();
assert_eq!(first, 0x00D3);
assert!(!zerovec.is_owned());
let mut zerovec = zerovec.into_owned();
assert!(zerovec.is_owned());
let first = zerovec.take_first().unwrap();
assert_eq!(first, 0x0119);
assert!(zerovec.is_owned());
Sourcepub fn take_last(&mut self) -> Option<T>
pub fn take_last(&mut self) -> Option<T>
Removes the last element of the ZeroVec. The ZeroVec remains in the same borrowed or owned state.
§Examples
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x01];
let mut zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert!(!zerovec.is_owned());
let last = zerovec.take_last().unwrap();
assert_eq!(last, 0x01CD);
assert!(!zerovec.is_owned());
let mut zerovec = zerovec.into_owned();
assert!(zerovec.is_owned());
let last = zerovec.take_last().unwrap();
assert_eq!(last, 0x01A5);
assert!(zerovec.is_owned());
Methods from Deref<Target = ZeroSlice<T>>§
Sourcepub fn as_zerovec(&self) -> ZeroVec<'_, T>
pub fn as_zerovec(&self) -> ZeroVec<'_, T>
Sourcepub fn as_bytes(&self) -> &[u8] ⓘ
pub fn as_bytes(&self) -> &[u8] ⓘ
Returns this slice as its underlying &[u8]
byte buffer representation.
Useful for serialization.
§Example
use zerovec::ZeroVec;
// The little-endian bytes correspond to the numbers on the following line.
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let nums: &[u16] = &[211, 281, 421, 32973];
let zerovec = ZeroVec::alloc_from_slice(nums);
assert_eq!(bytes, zerovec.as_bytes());
Sourcepub fn as_ule_slice(&self) -> &[T::ULE]
pub fn as_ule_slice(&self) -> &[T::ULE]
Dereferences this slice as &[T::ULE]
.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in this slice.
§Example
use zerovec::ule::AsULE;
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(4, zerovec.len());
assert_eq!(
bytes.len(),
zerovec.len() * std::mem::size_of::<<u16 as AsULE>::ULE>()
);
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns whether this slice is empty.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert!(!zerovec.is_empty());
let emptyvec: ZeroVec<u16> = ZeroVec::parse_bytes(&[]).expect("infallible");
assert!(emptyvec.is_empty());
Sourcepub fn get(&self, index: usize) -> Option<T>
pub fn get(&self, index: usize) -> Option<T>
Gets the element at the specified index. Returns None
if out of range.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(zerovec.get(2), Some(421));
assert_eq!(zerovec.get(4), None);
Sourcepub fn get_as_array<const N: usize>(&self) -> Option<[T; N]>
pub fn get_as_array<const N: usize>(&self) -> Option<[T; N]>
Gets the entire slice as an array of length N
. Returns None
if the slice
does not have exactly N
elements.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
let array: [u16; 4] =
zerovec.get_as_array().expect("should be 4 items in array");
assert_eq!(array[2], 421);
Sourcepub fn get_subslice(&self, range: Range<usize>) -> Option<&ZeroSlice<T>>
pub fn get_subslice(&self, range: Range<usize>) -> Option<&ZeroSlice<T>>
Gets a subslice of elements within a certain range. Returns None
if the range
is out of bounds of this ZeroSlice
.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(
zerovec.get_subslice(1..3),
Some(&*ZeroVec::from_slice_or_alloc(&[0x0119, 0x01A5]))
);
assert_eq!(zerovec.get_subslice(3..5), None);
Sourcepub fn get_ule_ref(&self, index: usize) -> Option<&T::ULE>
pub fn get_ule_ref(&self, index: usize) -> Option<&T::ULE>
Get a borrowed reference to the underlying ULE type at a specified index.
Prefer Self::get()
over this method where possible since working
directly with ULE
types is less ergonomic
Sourcepub fn cast<P>(&self) -> &ZeroSlice<P>
pub fn cast<P>(&self) -> &ZeroSlice<P>
Casts a ZeroSlice<T>
to a compatible ZeroSlice<P>
.
T
and P
are compatible if they have the same ULE
representation.
If the ULE
s of T
and P
are different, use Self::try_as_converted()
.
§Examples
use zerovec::ZeroSlice;
const BYTES: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
const ZS_U16: &ZeroSlice<u16> = {
match ZeroSlice::<u16>::try_from_bytes(BYTES) {
Ok(s) => s,
Err(_) => unreachable!(),
}
};
let zs_i16: &ZeroSlice<i16> = ZS_U16.cast();
assert_eq!(ZS_U16.get(3), Some(32973));
assert_eq!(zs_i16.get(3), Some(-32563));
Sourcepub fn try_as_converted<P: AsULE>(&self) -> Result<&ZeroSlice<P>, UleError>
pub fn try_as_converted<P: AsULE>(&self) -> Result<&ZeroSlice<P>, UleError>
Converts a &ZeroSlice<T>
into a &ZeroSlice<P>
.
The resulting slice will have the same length as the original slice
if and only if T::ULE
and P::ULE
are the same size.
If T
and P
have the exact same ULE
, use Self::cast()
.
§Examples
use zerovec::ZeroSlice;
const BYTES: &[u8] = &[0x7F, 0xF3, 0x01, 0x00, 0x49, 0xF6, 0x01, 0x00];
const ZS_U32: &ZeroSlice<u32> = {
match ZeroSlice::<u32>::try_from_bytes(BYTES) {
Ok(s) => s,
Err(_) => unreachable!(),
}
};
let zs_u8_4: &ZeroSlice<[u8; 4]> =
ZS_U32.try_as_converted().expect("valid code points");
assert_eq!(ZS_U32.get(0), Some(127871));
assert_eq!(zs_u8_4.get(0), Some([0x7F, 0xF3, 0x01, 0x00]));
Sourcepub fn first(&self) -> Option<T>
pub fn first(&self) -> Option<T>
Gets the first element. Returns None
if empty.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(zerovec.first(), Some(211));
Sourcepub fn last(&self) -> Option<T>
pub fn last(&self) -> Option<T>
Gets the last element. Returns None
if empty.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(zerovec.last(), Some(32973));
Sourcepub fn iter<'a>(&'a self) -> ZeroSliceIter<'a, T> ⓘ
pub fn iter<'a>(&'a self) -> ZeroSliceIter<'a, T> ⓘ
Gets an iterator over the elements.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
let mut it = zerovec.iter();
assert_eq!(it.next(), Some(211));
assert_eq!(it.next(), Some(281));
assert_eq!(it.next(), Some(421));
assert_eq!(it.next(), Some(32973));
assert_eq!(it.next(), None);
Sourcepub fn split_first(&self) -> Option<(T, &ZeroSlice<T>)>
pub fn split_first(&self) -> Option<(T, &ZeroSlice<T>)>
Returns a tuple with the first element and a subslice of the remaining elements.
§Example
use zerovec::ule::AsULE;
use zerovec::ZeroSlice;
const DATA: &ZeroSlice<u16> =
ZeroSlice::<u16>::from_ule_slice(&<u16 as AsULE>::ULE::from_array([
211, 281, 421, 32973,
]));
const EXPECTED_VALUE: (u16, &ZeroSlice<u16>) = (
211,
ZeroSlice::<u16>::from_ule_slice(&<u16 as AsULE>::ULE::from_array([
281, 421, 32973,
])),
);
assert_eq!(EXPECTED_VALUE, DATA.split_first().unwrap());
Sourcepub fn binary_search(&self, x: &T) -> Result<usize, usize>
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
Binary searches a sorted ZeroVec<T>
for the given element. For more information, see
the primitive function binary_search
.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(zerovec.binary_search(&281), Ok(1));
assert_eq!(zerovec.binary_search(&282), Err(2));
Sourcepub fn binary_search_by(
&self,
predicate: impl FnMut(T) -> Ordering,
) -> Result<usize, usize>
pub fn binary_search_by( &self, predicate: impl FnMut(T) -> Ordering, ) -> Result<usize, usize>
Binary searches a sorted ZeroVec<T>
based on a given predicate. For more information, see
the primitive function binary_search_by
.
§Example
use zerovec::ZeroVec;
let bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
let zerovec: ZeroVec<u16> =
ZeroVec::parse_bytes(bytes).expect("infallible");
assert_eq!(zerovec.binary_search_by(|x| x.cmp(&281)), Ok(1));
assert_eq!(zerovec.binary_search_by(|x| x.cmp(&282)), Err(2));
Trait Implementations§
Source§impl<T> EncodeAsVarULE<ZeroSlice<T>> for ZeroVec<'_, T>where
T: AsULE + 'static,
impl<T> EncodeAsVarULE<ZeroSlice<T>> for ZeroVec<'_, T>where
T: AsULE + 'static,
Source§fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R
fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R
cb
with a piecewise list of byte slices that when concatenated
produce the memory pattern of the corresponding instance of T
. Read moreSource§fn encode_var_ule_len(&self) -> usize
fn encode_var_ule_len(&self) -> usize
VarULE
typeSource§fn encode_var_ule_write(&self, dst: &mut [u8])
fn encode_var_ule_write(&self, dst: &mut [u8])
VarULE
type to the dst
buffer. dst
should
be the size of Self::encode_var_ule_len()
Source§impl<T: AsULE> FromIterator<T> for ZeroVec<'_, T>
impl<T: AsULE> FromIterator<T> for ZeroVec<'_, T>
Source§fn from_iter<I>(iter: I) -> Selfwhere
I: IntoIterator<Item = T>,
fn from_iter<I>(iter: I) -> Selfwhere
I: IntoIterator<Item = T>,
Creates an owned ZeroVec
from an iterator of values.
Source§impl<'a, T> MutableZeroVecLike<'a, T> for ZeroVec<'a, T>
impl<'a, T> MutableZeroVecLike<'a, T> for ZeroVec<'a, T>
Source§fn zvl_insert(&mut self, index: usize, value: &T)
fn zvl_insert(&mut self, index: usize, value: &T)
index
Source§fn zvl_remove(&mut self, index: usize) -> T
fn zvl_remove(&mut self, index: usize) -> T
index
(panicking if nonexistant)Source§fn zvl_replace(&mut self, index: usize, value: &T) -> T
fn zvl_replace(&mut self, index: usize, value: &T) -> T
index
with another one, returning the old elementSource§fn zvl_with_capacity(cap: usize) -> Self
fn zvl_with_capacity(cap: usize) -> Self
Source§fn zvl_reserve(&mut self, addl: usize)
fn zvl_reserve(&mut self, addl: usize)
addl
additional elementsSource§fn owned_as_t(o: &Self::OwnedType) -> &T
fn owned_as_t(o: &Self::OwnedType) -> &T
Source§fn zvl_from_borrowed(b: &'a ZeroSlice<T>) -> Self
fn zvl_from_borrowed(b: &'a ZeroSlice<T>) -> Self
Source§fn zvl_as_borrowed_inner(&self) -> Option<&'a ZeroSlice<T>>
fn zvl_as_borrowed_inner(&self) -> Option<&'a ZeroSlice<T>>
None
if the data is owned. Read moreSource§fn zvl_permute(&mut self, permutation: &mut [usize])
fn zvl_permute(&mut self, permutation: &mut [usize])
before.zvl_get(permutation[i]) == after.zvl_get(i)
. Read moreSource§impl<'a, T: AsULE + Ord> Ord for ZeroVec<'a, T>
impl<'a, T: AsULE + Ord> Ord for ZeroVec<'a, T>
Source§impl<'a, T: AsULE + PartialOrd> PartialOrd for ZeroVec<'a, T>
impl<'a, T: AsULE + PartialOrd> PartialOrd for ZeroVec<'a, T>
Source§impl<'a, T: 'static + AsULE> Yokeable<'a> for ZeroVec<'static, T>
This impl requires enabling the optional yoke
Cargo feature of the zerovec
crate
impl<'a, T: 'static + AsULE> Yokeable<'a> for ZeroVec<'static, T>
This impl requires enabling the optional yoke
Cargo feature of the zerovec
crate
Source§type Output = ZeroVec<'a, T>
type Output = ZeroVec<'a, T>
Self
with the 'static
replaced with 'a
, i.e. Self<'a>
Source§fn transform_owned(self) -> Self::Output
fn transform_owned(self) -> Self::Output
Source§impl<'a, T> ZeroVecLike<T> for ZeroVec<'a, T>
impl<'a, T> ZeroVecLike<T> for ZeroVec<'a, T>
Source§type SliceVariant = ZeroSlice<T>
type SliceVariant = ZeroSlice<T>
Source§fn zvl_new_borrowed() -> &'static Self::SliceVariant
fn zvl_new_borrowed() -> &'static Self::SliceVariant
Source§fn zvl_binary_search(&self, k: &T) -> Result<usize, usize>where
T: Ord,
fn zvl_binary_search(&self, k: &T) -> Result<usize, usize>where
T: Ord,
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.Source§fn zvl_binary_search_in_range(
&self,
k: &T,
range: Range<usize>,
) -> Option<Result<usize, usize>>where
T: Ord,
fn zvl_binary_search_in_range(
&self,
k: &T,
range: Range<usize>,
) -> Option<Result<usize, usize>>where
T: Ord,
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.Source§fn zvl_binary_search_by(
&self,
predicate: impl FnMut(&T) -> Ordering,
) -> Result<usize, usize>
fn zvl_binary_search_by( &self, predicate: impl FnMut(&T) -> Ordering, ) -> Result<usize, usize>
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.Source§fn zvl_binary_search_in_range_by(
&self,
predicate: impl FnMut(&T) -> Ordering,
range: Range<usize>,
) -> Option<Result<usize, usize>>
fn zvl_binary_search_in_range_by( &self, predicate: impl FnMut(&T) -> Ordering, range: Range<usize>, ) -> Option<Result<usize, usize>>
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.Source§fn zvl_as_borrowed(&self) -> &ZeroSlice<T>
fn zvl_as_borrowed(&self) -> &ZeroSlice<T>
&self
. Read moreSource§fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R
fn zvl_get_as_t<R>(g: &Self::GetType, f: impl FnOnce(&T) -> R) -> R
Source§fn zvl_is_ascending(&self) -> boolwhere
T: Ord,
fn zvl_is_ascending(&self) -> boolwhere
T: Ord,
T
s Ord
implSource§fn zvl_is_empty(&self) -> bool
fn zvl_is_empty(&self) -> bool
impl<T> Eq for ZeroVec<'_, T>
impl<'a, T: AsULE> Send for ZeroVec<'a, T>
impl<'a, T: AsULE> Sync for ZeroVec<'a, T>
Auto Trait Implementations§
impl<'a, T> Freeze for ZeroVec<'a, T>
impl<'a, T> RefUnwindSafe for ZeroVec<'a, T>
impl<'a, T> Unpin for ZeroVec<'a, T>
impl<'a, T> UnwindSafe for ZeroVec<'a, T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> ErasedDestructor for Twhere
T: 'static,
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.
Size: 24 bytes