use std::{
borrow::{Borrow, BorrowMut},
cmp::Ordering,
fmt,
iter::FromIterator,
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
ptr, slice,
};
use crate::bindings::{
_vec_alloc_internal, _vec_resize_internal, VEC_MIN_ALIGN, vec_attr_t, vec_free_not_inline,
vec_header_t,
};
pub struct VecRef<T>(foreign_types::Opaque, std::marker::PhantomData<T>);
impl<T> VecRef<T> {
#[inline(always)]
pub unsafe fn from_raw<'a>(ptr: *const T) -> &'a Self {
unsafe { &*(ptr as *mut _) }
}
#[inline(always)]
pub unsafe fn from_raw_mut<'a>(ptr: *mut T) -> &'a mut Self {
unsafe { &mut *(ptr as *mut _) }
}
#[inline(always)]
pub unsafe fn from_raw_opt<'a>(ptr: *const T) -> Option<&'a Self> {
unsafe {
if ptr.is_null() {
None
} else {
Some(&*(ptr as *mut _))
}
}
}
#[inline(always)]
pub unsafe fn from_raw_mut_opt<'a>(ptr: *mut T) -> Option<&'a mut Self> {
unsafe {
if ptr.is_null() {
None
} else {
Some(&mut *(ptr as *mut _))
}
}
}
#[inline(always)]
pub const fn as_ptr(&self) -> *const T {
self as *const _ as *const _
}
#[inline(always)]
pub const fn as_mut_ptr(&self) -> *mut T {
self as *const _ as *mut _
}
fn as_vec_header_ptr(&self) -> *mut vec_header_t {
unsafe {
let ptr: *mut vec_header_t = self.as_mut_ptr().cast();
ptr.sub(1)
}
}
#[inline]
pub fn len(&self) -> usize {
unsafe { (*self.as_vec_header_ptr()).len as usize }
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn capacity(&self) -> usize {
unsafe {
let hdr = self.as_vec_header_ptr();
((*hdr).len + (*hdr).grow_elts as u32) as usize
}
}
pub fn remove(&mut self, index: usize) -> T {
let hdr = self.as_vec_header_ptr();
unsafe {
let len = (*hdr).len as usize;
assert!(
index < len,
"removal index (is {index}) should be < len (is {len})"
);
let ptr = self.as_mut_ptr().add(index);
let ret = ptr::read(ptr);
ptr::copy(ptr.add(1), ptr, len - index - 1);
(*hdr).len = len as u32 - 1;
(*hdr).grow_elts += 1;
ret
}
}
pub fn pop(&mut self) -> Option<T> {
let hdr = self.as_vec_header_ptr();
unsafe {
let len = (*hdr).len as usize;
if len == 0 {
None
} else {
(*hdr).len = len as u32 - 1;
(*hdr).grow_elts += 1;
Some(ptr::read(self.as_ptr().add(len - 1)))
}
}
}
pub fn clear(&mut self) {
let elems: *mut [T] = self.as_mut_slice();
unsafe {
let hdr = self.as_vec_header_ptr();
let len = (*hdr).len;
let old_grow = (*hdr).grow_elts as u32;
let cap = len.saturating_add(old_grow);
(*hdr).len = 0;
(*hdr).grow_elts = cap.try_into().unwrap_or(u8::MAX);
ptr::drop_in_place(elems);
}
}
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
}
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
unsafe {
slice::from_raw_parts_mut(
self.as_ptr().add(self.len()) as *mut MaybeUninit<T>,
self.capacity() - self.len(),
)
}
}
pub unsafe fn set_len(&mut self, new_len: usize) {
unsafe {
debug_assert!(new_len <= self.capacity());
let hdr = self.as_vec_header_ptr();
let new_grow_elts = self.capacity() - new_len;
(*hdr).len = new_len as u32;
(*hdr).grow_elts = new_grow_elts.try_into().unwrap_or(u8::MAX);
}
}
}
impl<T> Deref for VecRef<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> DerefMut for VecRef<T> {
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T: fmt::Debug> fmt::Debug for VecRef<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.as_slice(), f)
}
}
impl<T> AsRef<VecRef<T>> for VecRef<T> {
fn as_ref(&self) -> &VecRef<T> {
self
}
}
impl<T> AsMut<VecRef<T>> for VecRef<T> {
fn as_mut(&mut self) -> &mut VecRef<T> {
self
}
}
impl<T> AsRef<[T]> for VecRef<T> {
fn as_ref(&self) -> &[T] {
self
}
}
impl<T> AsMut<[T]> for VecRef<T> {
fn as_mut(&mut self) -> &mut [T] {
self
}
}
impl<T> PartialOrd<VecRef<T>> for VecRef<T>
where
T: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &VecRef<T>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<T: Eq> Eq for VecRef<T> {}
impl<T: Ord> Ord for VecRef<T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
unsafe impl<T> Send for VecRef<T> where T: Send {}
pub struct Vec<T>(*mut T);
impl<T> Vec<T> {
pub fn len(&self) -> usize {
if self.as_ptr().is_null() {
0
} else {
unsafe { VecRef::from_raw(self.as_ptr()).len() }
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn capacity(&self) -> usize {
if self.as_ptr().is_null() {
0
} else {
unsafe { VecRef::from_raw(self.as_ptr()).capacity() }
}
}
unsafe fn as_vec_header_ptr(&self) -> *mut vec_header_t {
unsafe { (self.as_mut_ptr() as *mut vec_header_t).sub(1) }
}
pub fn as_slice(&self) -> &[T] {
let len = self.len();
if len == 0 {
&[]
} else {
unsafe { slice::from_raw_parts(self.as_ptr(), len) }
}
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
let len = self.len();
if len == 0 {
&mut []
} else {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), len) }
}
}
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
if self.as_ptr().is_null() {
&mut []
} else {
unsafe { VecRef::from_raw_mut(self.as_mut_ptr()).spare_capacity_mut() }
}
}
pub unsafe fn set_len(&mut self, new_len: usize) {
if self.as_ptr().is_null() {
debug_assert_eq!(new_len, 0);
return;
}
unsafe { VecRef::from_raw_mut(self.as_mut_ptr()).set_len(new_len) }
}
pub unsafe fn from_raw(ptr: *mut T) -> Vec<T> {
Vec(ptr)
}
pub fn with_capacity(capacity: usize) -> Self {
let align = std::mem::align_of::<T>() as u16;
let attr = vec_attr_t {
align: align.max(VEC_MIN_ALIGN as u16),
hdr_sz: 0, heap: std::ptr::null_mut(),
elt_sz: std::mem::size_of::<T>() as u32,
};
unsafe {
let mut v = Self(_vec_alloc_internal(capacity as u64, &attr).cast());
v.set_len(0);
v
}
}
pub const fn new() -> Self {
Self(std::ptr::null_mut())
}
pub fn reserve(&mut self, additional: usize) {
let align = std::mem::align_of::<T>() as u16;
let len = self.len();
let new_len = len.checked_add(additional).unwrap_or_else(|| {
panic!("Overflow on adding {additional} elements to vec of len {len}")
});
let new_len = u32::try_from(new_len).unwrap_or_else(|_| {
panic!("Overflow on adding {additional} elements to vec of len {len}")
});
let attr = vec_attr_t {
align: align.max(VEC_MIN_ALIGN as u16),
hdr_sz: 0, heap: std::ptr::null_mut(),
elt_sz: std::mem::size_of::<T>() as u32,
};
unsafe {
let ptr = _vec_resize_internal(self.as_mut_ptr().cast(), new_len.into(), &attr);
self.0 = ptr.cast();
self.set_len(len);
}
}
pub fn push(&mut self, value: T) {
let len = self.len();
if len == self.capacity() {
self.reserve(1);
}
unsafe {
let end = self.as_mut_ptr().add(len);
ptr::write(end, value);
let hdr = self.as_vec_header_ptr();
(*hdr).len = len as u32 + 1;
(*hdr).grow_elts -= 1;
}
}
pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T {
let len = self.len();
let capacity = self.capacity();
assert!(
index <= len,
"insertion index (is {index}) should be <= len (is {len})"
);
if len == capacity {
self.reserve(1);
}
unsafe {
let p = self.as_mut_ptr().add(index);
if index < len {
ptr::copy(p, p.add(1), len - index);
}
ptr::write(p, element);
let hdr = self.as_vec_header_ptr();
(*hdr).len = len as u32 + 1;
(*hdr).grow_elts -= 1;
&mut *p
}
}
#[must_use = "losing the pointer will leak the vector"]
pub fn into_raw(self) -> *mut T {
let v = ManuallyDrop::new(self);
v.as_mut_ptr()
}
#[inline(always)]
pub const fn as_ptr(&self) -> *const T {
self.0
}
#[inline(always)]
pub const fn as_mut_ptr(&self) -> *mut T {
self.0
}
}
impl<T> Default for Vec<T> {
fn default() -> Vec<T> {
Vec::new()
}
}
impl<T: Clone> Vec<T> {
pub fn extend_with(&mut self, n: usize, value: T) {
self.reserve(n);
let new_len = self.len() + n;
unsafe {
let mut ptr = self.as_mut_ptr().add(self.len());
for _ in 1..n {
ptr::write(ptr, value.clone());
ptr = ptr.add(1);
}
if n > 0 {
ptr::write(ptr, value);
}
self.set_len(new_len);
}
}
}
impl<T> Extend<T> for Vec<T> {
#[track_caller]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
let mut iter = iter.into_iter();
while let Some(element) = iter.next() {
let len = self.len();
if len == self.capacity() {
let (lower, _) = iter.size_hint();
self.reserve(lower.saturating_add(1));
}
unsafe {
ptr::write(self.as_mut_ptr().add(len), element);
self.set_len(len + 1);
}
}
}
}
impl<'a, T: Copy + 'a> Extend<&'a T> for Vec<T> {
#[track_caller]
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
let mut iter = iter.into_iter();
while let Some(element) = iter.next() {
let len = self.len();
if len == self.capacity() {
let (lower, _) = iter.size_hint();
self.reserve(lower.saturating_add(1));
}
unsafe {
ptr::write(self.as_mut_ptr().add(len), *element);
self.set_len(len + 1);
}
}
}
}
impl<T> Drop for Vec<T> {
fn drop(&mut self) {
if self.as_mut_ptr().is_null() {
return;
}
unsafe {
let elems: *mut [T] = self.as_mut_slice();
ptr::drop_in_place(elems);
vec_free_not_inline(self.as_mut_ptr().cast())
}
}
}
impl<T> Deref for Vec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> DerefMut for Vec<T> {
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T> Vec<T> {
pub fn remove(&mut self, index: usize) -> T {
if self.as_mut_ptr().is_null() {
panic!("removal index (is {index}) should be <= len (is 0)");
}
unsafe { VecRef::from_raw_mut(self.as_mut_ptr()).remove(index) }
}
pub fn pop(&mut self) -> Option<T> {
if self.as_mut_ptr().is_null() {
None
} else {
unsafe { VecRef::from_raw_mut(self.as_mut_ptr()).pop() }
}
}
pub fn clear(&mut self) {
if self.as_mut_ptr().is_null() {
return;
}
unsafe { VecRef::from_raw_mut(self.as_mut_ptr()).clear() }
}
pub fn as_vec_ref(&self) -> Option<&VecRef<T>> {
if self.as_ptr().is_null() {
None
} else {
Some(unsafe { VecRef::from_raw(self.as_ptr()) })
}
}
pub fn as_vec_ref_mut(&mut self) -> Option<&mut VecRef<T>> {
if self.as_mut_ptr().is_null() {
None
} else {
Some(unsafe { VecRef::from_raw_mut(self.as_mut_ptr()) })
}
}
}
impl<T: Clone> Clone for Vec<T> {
fn clone(&self) -> Self {
self.as_slice().to_vpp_vec()
}
}
impl<T: fmt::Debug> fmt::Debug for Vec<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.as_slice(), f)
}
}
impl<T> AsRef<Vec<T>> for Vec<T> {
fn as_ref(&self) -> &Vec<T> {
self
}
}
impl<T> AsMut<Vec<T>> for Vec<T> {
fn as_mut(&mut self) -> &mut Vec<T> {
self
}
}
impl<T> AsRef<[T]> for Vec<T> {
fn as_ref(&self) -> &[T] {
self
}
}
impl<T> AsMut<[T]> for Vec<T> {
fn as_mut(&mut self) -> &mut [T] {
self
}
}
impl<T> Borrow<[T]> for Vec<T> {
fn borrow(&self) -> &[T] {
&self[..]
}
}
impl<T> BorrowMut<[T]> for Vec<T> {
fn borrow_mut(&mut self) -> &mut [T] {
&mut self[..]
}
}
impl<T> PartialOrd<Vec<T>> for Vec<T>
where
T: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<T: Eq> Eq for Vec<T> {}
impl<T: Ord> Ord for Vec<T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<T> FromIterator<T> for Vec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (lower_size, upper_size) = iter.size_hint();
let size = upper_size.unwrap_or(lower_size);
let mut vec = Vec::with_capacity(size);
for item in iter {
vec.push(item);
}
vec
}
}
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
let ptr = self.0;
let len = self.len();
std::mem::forget(self);
let end_ptr = if len == 0 {
ptr
} else {
unsafe { ptr.add(len) }
};
IntoIter {
start_ptr: ptr,
ptr,
end_ptr,
len,
}
}
}
pub struct IntoIter<T> {
start_ptr: *mut T,
ptr: *mut T,
end_ptr: *mut T,
len: usize,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
unsafe {
let item = ptr::read(self.ptr);
self.ptr = self.ptr.add(1);
self.len -= 1;
Some(item)
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<T> DoubleEndedIterator for IntoIter<T> {
fn next_back(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
unsafe {
self.end_ptr = self.end_ptr.sub(1);
let item = ptr::read(self.end_ptr);
self.len -= 1;
Some(item)
}
}
}
}
impl<T> ExactSizeIterator for IntoIter<T> {}
impl<T> std::iter::FusedIterator for IntoIter<T> {}
impl<T> Default for IntoIter<T> {
fn default() -> Self {
IntoIter {
start_ptr: std::ptr::null_mut(),
ptr: std::ptr::null_mut(),
end_ptr: std::ptr::null_mut(),
len: 0,
}
}
}
impl<T: Clone> Clone for IntoIter<T> {
fn clone(&self) -> Self {
if self.len == 0 {
return IntoIter::default();
}
let mut new_vec = Vec::with_capacity(self.len);
unsafe {
for i in 0..self.len {
let item = &*self.ptr.add(i);
new_vec.push(item.clone());
}
}
new_vec.into_iter()
}
}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
if self.len > 0 {
unsafe {
let slice = slice::from_raw_parts_mut(self.ptr, self.len);
ptr::drop_in_place(slice);
}
}
if !self.start_ptr.is_null() {
unsafe {
vec_free_not_inline(self.start_ptr.cast());
}
}
}
}
pub trait SliceExt<T> {
fn to_vpp_vec(&self) -> Vec<T>
where
T: Clone;
}
impl<T> SliceExt<T> for [T] {
fn to_vpp_vec(&self) -> Vec<T>
where
T: Clone,
{
let len = self.len();
let mut vec = Vec::with_capacity(len);
let slots = vec.spare_capacity_mut();
for (i, b) in self.iter().enumerate().take(slots.len()) {
slots[i].write(b.clone());
}
unsafe {
vec.set_len(self.len());
}
vec
}
}
macro_rules! __impl_slice_eq {
([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?) => {
impl<T, U, $($vars)*> PartialEq<$rhs> for $lhs
where
T: PartialEq<U>,
$($ty: $bound)?
{
#[inline]
fn eq(&self, other: &$rhs) -> bool { self[..] == other[..] }
}
}
}
__impl_slice_eq! { [] VecRef<T>, VecRef<U> }
__impl_slice_eq! { [] VecRef<T>, std::vec::Vec<U> }
__impl_slice_eq! { [] VecRef<T>, &[U] }
__impl_slice_eq! { [] VecRef<T>, &mut [U] }
__impl_slice_eq! { [] VecRef<T>, [U] }
__impl_slice_eq! { [] VecRef<T>, Vec<U> }
__impl_slice_eq! { [] Vec<T>, Vec<U> }
__impl_slice_eq! { [] Vec<T>, VecRef<U> }
__impl_slice_eq! { [] Vec<T>, std::vec::Vec<U> }
__impl_slice_eq! { [] Vec<T>, &[U] }
__impl_slice_eq! { [] Vec<T>, &mut [U] }
__impl_slice_eq! { [] Vec<T>, [U] }
__impl_slice_eq! { [const N: usize] VecRef<T>, [U; N] }
__impl_slice_eq! { [const N: usize] VecRef<T>, &[U; N] }
__impl_slice_eq! { [const N: usize] Vec<T>, [U; N] }
__impl_slice_eq! { [const N: usize] Vec<T>, &[U; N] }
unsafe impl<T> Send for Vec<T> where T: Send {}
#[macro_export]
macro_rules! vec {
() => (
$crate::vppinfra::vec::Vec::new()
);
($elem:expr; $n:expr) => ({
let mut v = $crate::vppinfra::vec::Vec::with_capacity($n);
v.extend_with($n, $elem);
v
});
($($x:expr),+ $(,)?) => (
$crate::vppinfra::vec::SliceExt::to_vpp_vec(
[$($x),+].as_slice()
)
);
}
#[cfg(test)]
mod tests {
use crate::vppinfra::{
VecRef, clib_mem_init,
vec::{IntoIter, SliceExt, Vec},
};
#[test]
fn push_pop() {
clib_mem_init();
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
assert_eq!(v.len(), 3);
assert!(v.capacity() >= 3);
assert_eq!(v.pop(), Some(3));
assert_eq!(v.pop(), Some(2));
assert_eq!(v.pop(), Some(1));
assert_eq!(v.pop(), None);
}
#[test]
fn test_macro() {
clib_mem_init();
let v: Vec<u8> = vec![];
assert_eq!(v.len(), 0);
let v = vec![1, 2, 3];
assert_eq!(v[0], 1);
assert_eq!(v[1], 2);
assert_eq!(v[2], 3);
let v = vec![1; 3];
assert_eq!(v[0], 1);
assert_eq!(v[1], 1);
assert_eq!(v[2], 1);
}
#[test]
fn extend_from() {
clib_mem_init();
let mut v: Vec<u32> = Vec::new();
v.extend(&[1, 2, 3]);
assert_eq!(v, [1, 2, 3]);
let mut v = vec![1u32];
v.extend([2, 3].as_slice());
assert_eq!(v, [1, 2, 3]);
let mut v = Vec::new();
v.extend([1u32, 2, 3]);
assert_eq!(v, [1, 2, 3]);
let mut v = vec![1u32];
v.extend([2, 3]);
assert_eq!(v, [1, 2, 3]);
}
#[test]
fn remove() {
clib_mem_init();
let mut v = vec![1, 2, 3, 4];
let removed = v.remove(1);
assert_eq!(removed, 2);
assert_eq!(v.len(), 3);
assert_eq!(v[0], 1);
assert_eq!(v[1], 3);
assert_eq!(v[2], 4);
let removed = v.remove(2);
assert_eq!(removed, 4);
assert_eq!(v.len(), 2);
assert_eq!(v[0], 1);
assert_eq!(v[1], 3);
}
#[test]
fn insert_mut() {
clib_mem_init();
let mut v = vec![1, 3];
let slot = v.insert_mut(1, 2);
assert_eq!(*slot, 2);
assert_eq!(v.len(), 3);
assert_eq!(v[0], 1);
assert_eq!(v[1], 2);
assert_eq!(v[2], 3);
let slot = v.insert_mut(3, 4);
assert_eq!(*slot, 4);
assert_eq!(v.len(), 4);
assert_eq!(v[0], 1);
assert_eq!(v[1], 2);
assert_eq!(v[2], 3);
assert_eq!(v[3], 4);
}
#[test]
fn clear_preserves_capacity() {
clib_mem_init();
let mut v = vec![10, 20, 30];
let cap = v.capacity();
v.clear();
assert_eq!(v.len(), 0);
assert!(
v.capacity() >= cap,
"New capacity {} should be >= old capacity {}",
v.capacity(),
cap
);
}
#[test]
fn into_raw_and_from_raw_roundtrip() {
clib_mem_init();
let mut v = Vec::new();
v.push(7);
v.push(8);
let raw = v.into_raw();
unsafe {
let v2 = Vec::from_raw(raw);
assert_eq!(v2.len(), 2);
assert_eq!(v2[0], 7);
assert_eq!(v2[1], 8);
}
}
#[test]
fn extend_with_clones() {
clib_mem_init();
let mut v: Vec<String> = Vec::new();
v.extend_with(3, "x".to_string());
assert_eq!(v.len(), 3);
assert_eq!(v[0], "x");
assert_eq!(v[1], "x");
assert_eq!(v[2], "x");
}
#[test]
fn slice_to_vpp_vec() {
clib_mem_init();
let s = [42u16, 43u16];
let v = s.as_slice().to_vpp_vec();
assert_eq!(v.len(), 2);
assert_eq!(v[0], 42);
assert_eq!(v[1], 43);
}
#[test]
fn clone_vec() {
clib_mem_init();
let v = vec![5u8, 6u8];
let v2 = v.clone();
assert_eq!(v2.len(), 2);
assert_eq!(v2[0], 5);
assert_eq!(v2[1], 6);
}
#[test]
fn spare_capacity_and_set_len() {
clib_mem_init();
let mut v: Vec<u32> = Vec::with_capacity(4);
let slots = v.spare_capacity_mut();
slots[0].write(100);
slots[1].write(200);
unsafe { v.set_len(2) }
assert_eq!(v.len(), 2);
assert_eq!(v[0], 100);
assert_eq!(v[1], 200);
}
#[test]
fn empty_vec_is_null() {
clib_mem_init();
let mut v: Vec<u8> = Vec::new();
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), 0);
assert_eq!(v.as_slice(), &[]);
assert!(
v.as_ptr().is_null(),
"expected pointer for empty Vec to be null"
);
assert_eq!(v.spare_capacity_mut().len(), 0);
assert_eq!(v.pop(), None);
v.clear();
let raw = v.into_raw();
assert!(
raw.is_null(),
"expected raw pointer for empty Vec to be null"
);
let v = unsafe { Vec::from_raw(raw) };
assert_eq!(v.as_vec_ref(), None);
let v = unsafe { VecRef::from_raw_opt(std::ptr::null::<u8>()) };
assert_eq!(v, None);
let v = unsafe { VecRef::from_raw_mut_opt(std::ptr::null_mut::<u8>()) };
assert_eq!(v, None);
}
#[test]
fn test_from_iterator() {
clib_mem_init();
let data = vec![1, 2, 3, 4, 5];
let v: Vec<_> = data.into_iter().collect();
assert_eq!(v.as_slice(), &[1, 2, 3, 4, 5]);
}
#[test]
fn test_into_iter() {
clib_mem_init();
let data = vec!["A".to_string(), "B".to_string(), "C".to_string()];
let mut iter = data.into_iter();
assert_eq!(iter.next().as_deref(), Some("A"));
}
#[test]
fn test_into_iter_default() {
clib_mem_init();
let mut iter: IntoIter<i32> = Default::default();
assert_eq!(iter.next(), None);
assert_eq!(iter.len(), 0);
}
#[test]
fn test_into_iter_clone() {
clib_mem_init();
let v = vec![1, 2, 3, 4, 5];
let mut iter1 = v.into_iter();
assert_eq!(iter1.next(), Some(1));
let mut iter2 = iter1.clone();
assert_eq!(iter1.next(), Some(2));
assert_eq!(iter2.next(), Some(2));
assert_eq!(iter1.next(), Some(3));
assert_eq!(iter2.next(), Some(3));
assert_eq!(iter1.collect::<Vec<_>>(), vec![4, 5]);
assert_eq!(iter2.collect::<Vec<_>>(), vec![4, 5]);
let mut iter1: IntoIter<i32> = IntoIter::default();
let mut iter2 = iter1.clone();
assert_eq!(iter2.next(), None);
assert_eq!(iter1.next(), None);
}
#[test]
fn test_into_iter_double_ended() {
clib_mem_init();
let v = vec![1, 2, 3, 4, 5];
let mut iter = v.into_iter();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next_back(), Some(5));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next_back(), Some(4));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next(), None);
}
}