use alloc::borrow::Cow;
use alloc::boxed::Box;
use alloc::collections::TryReserveError;
use alloc::ffi::CString;
use alloc::string::String;
use alloc::vec::{self, Drain, Splice, Vec};
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::iter::FromIterator;
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::ops::{Deref, DerefMut, Index, IndexMut, RangeBounds};
use core::{fmt, slice};
#[cfg(feature = "std")]
use std::io::{IoSlice, Result as IoResult, Write};
#[cfg(feature = "bincode")]
use bincode::de::{BorrowDecode, BorrowDecoder, Decode, Decoder};
#[cfg(feature = "bincode")]
use bincode::enc::{Encode, Encoder};
#[cfg(feature = "bincode")]
use bincode::error::{DecodeError, EncodeError};
#[cfg(all(feature = "alloc", feature = "serde"))]
use serde::de::{Deserialize, Deserializer};
#[cfg(feature = "serde")]
use serde::ser::{Serialize, Serializer};
use crate::{TiEnumerated, TiRangeBounds, TiSlice, TiSliceIndex};
#[repr(transparent)]
pub struct TiVec<K, V> {
pub raw: Vec<V>,
_marker: PhantomData<fn(K) -> K>,
}
impl<K, V> TiVec<K, V> {
#[inline]
#[must_use]
pub const fn new() -> Self {
Self {
raw: Vec::new(),
_marker: PhantomData,
}
}
#[inline]
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
raw: Vec::with_capacity(capacity),
_marker: PhantomData,
}
}
#[inline]
pub unsafe fn from_raw_parts(ptr: *mut V, length: usize, capacity: usize) -> Self {
Self {
raw: unsafe { Vec::from_raw_parts(ptr, length, capacity) },
_marker: PhantomData,
}
}
#[inline]
#[must_use]
pub const fn from_ref(raw: &Vec<V>) -> &Self {
unsafe { &*core::ptr::from_ref::<Vec<V>>(raw).cast::<Self>() }
}
#[inline]
pub const fn from_mut(raw: &mut Vec<V>) -> &mut Self {
unsafe { &mut *core::ptr::from_mut::<Vec<V>>(raw).cast::<Self>() }
}
#[inline]
#[must_use]
pub const fn capacity(&self) -> usize {
self.raw.capacity()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.raw.reserve(additional);
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.raw.reserve_exact(additional);
}
#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.raw.try_reserve(additional)
}
#[inline]
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.raw.try_reserve_exact(additional)
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.raw.shrink_to_fit();
}
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) {
self.raw.shrink_to(min_capacity);
}
#[inline]
#[must_use]
pub fn into_boxed_slice(self) -> Box<TiSlice<K, V>> {
self.raw.into_boxed_slice().into()
}
#[inline]
pub fn truncate(&mut self, len: usize) {
self.raw.truncate(len);
}
#[inline]
#[must_use]
pub const fn as_slice(&self) -> &TiSlice<K, V> {
TiSlice::from_ref(self.raw.as_slice())
}
#[inline]
pub const fn as_mut_slice(&mut self) -> &mut TiSlice<K, V> {
TiSlice::from_mut(self.raw.as_mut_slice())
}
#[inline]
#[must_use]
pub const fn as_ptr(&self) -> *const V {
self.raw.as_ptr()
}
#[inline]
pub const fn as_mut_ptr(&mut self) -> *mut V {
self.raw.as_mut_ptr()
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
unsafe { self.raw.set_len(new_len) };
}
#[inline]
pub fn swap_remove(&mut self, index: K) -> V
where
K: Into<usize>,
{
self.raw.swap_remove(index.into())
}
#[inline]
pub fn insert(&mut self, index: K, element: V)
where
K: Into<usize>,
{
self.raw.insert(index.into(), element);
}
#[inline]
pub fn remove(&mut self, index: K) -> V
where
K: Into<usize>,
{
self.raw.remove(index.into())
}
#[inline]
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&V) -> bool,
{
self.raw.retain(f);
}
#[inline]
pub fn retain_mut<F>(&mut self, f: F)
where
F: FnMut(&mut V) -> bool,
{
self.raw.retain_mut(f);
}
#[inline]
pub fn dedup_by_key<F, K2>(&mut self, key: F)
where
F: FnMut(&mut V) -> K2,
K2: PartialEq,
{
self.raw.dedup_by_key(key);
}
#[inline]
pub fn dedup_by<F>(&mut self, same_bucket: F)
where
F: FnMut(&mut V, &mut V) -> bool,
{
self.raw.dedup_by(same_bucket);
}
#[inline]
pub fn push(&mut self, value: V) {
self.raw.push(value);
}
#[inline]
pub fn push_and_get_key(&mut self, value: V) -> K
where
usize: Into<K>,
{
let key = self.next_key();
self.raw.push(value);
key
}
#[inline]
pub fn pop(&mut self) -> Option<V> {
self.raw.pop()
}
#[inline]
pub fn pop_key_value(&mut self) -> Option<(K, V)>
where
usize: Into<K>,
{
self.raw.pop().map(|value| (self.raw.len().into(), value))
}
#[inline]
pub fn pop_if(&mut self, predicate: impl FnOnce(&mut V) -> bool) -> Option<V> {
self.raw.pop_if(predicate)
}
#[inline]
pub fn pop_key_value_if(&mut self, predicate: impl FnOnce(&mut V) -> bool) -> Option<(K, V)>
where
usize: Into<K>,
{
self.raw
.pop_if(predicate)
.map(|value| (self.raw.len().into(), value))
}
#[inline]
pub fn append(&mut self, other: &mut Self) {
self.raw.append(&mut other.raw);
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> Drain<'_, V>
where
R: TiRangeBounds<K>,
{
self.raw.drain(range.into_range())
}
#[inline]
pub fn drain_enumerated<R>(&mut self, range: R) -> TiEnumerated<Drain<'_, V>, K, V>
where
usize: Into<K>,
R: TiRangeBounds<K>,
{
self.raw
.drain(range.into_range())
.enumerate()
.map(|(key, value)| (key.into(), value))
}
#[inline]
pub fn clear(&mut self) {
self.raw.clear();
}
#[inline]
#[must_use]
pub const fn len(&self) -> usize {
self.raw.len()
}
#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.raw.is_empty()
}
#[inline]
#[must_use = "use `.truncate()` if you don't need the other half"]
pub fn split_off(&mut self, at: K) -> Self
where
K: Into<usize>,
{
self.raw.split_off(at.into()).into()
}
#[inline]
pub fn resize_with<F>(&mut self, new_len: usize, f: F)
where
F: FnMut() -> V,
{
self.raw.resize_with(new_len, f);
}
#[inline]
pub fn resize(&mut self, new_len: usize, value: V)
where
V: Clone,
{
self.raw.resize(new_len, value);
}
#[expect(clippy::must_use_candidate, reason = "not used in `Vec::leak`")]
#[inline]
pub fn leak<'a>(self) -> &'a mut TiSlice<K, V> {
self.raw.leak().as_mut()
}
#[inline]
pub fn spare_capacity_mut(&mut self) -> &mut TiSlice<K, MaybeUninit<V>> {
self.raw.spare_capacity_mut().as_mut()
}
#[inline]
pub fn extend_from_slice(&mut self, other: &TiSlice<K, V>)
where
V: Clone,
{
self.raw.extend_from_slice(&other.raw);
}
#[inline]
pub fn extend_from_within<R>(&mut self, src: R)
where
V: Clone,
R: RangeBounds<usize>,
{
self.raw.extend_from_within(src);
}
#[inline]
pub fn dedup(&mut self)
where
V: PartialEq,
{
self.raw.dedup();
}
#[inline]
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
where
R: TiRangeBounds<K>,
I: IntoIterator<Item = V>,
{
self.raw.splice(range.into_range(), replace_with)
}
#[inline]
pub fn into_iter_enumerated(self) -> TiEnumerated<vec::IntoIter<V>, K, V>
where
usize: Into<K>,
{
self.raw
.into_iter()
.enumerate()
.map(|(key, value)| (key.into(), value))
}
}
impl<K, V> fmt::Debug for TiVec<K, V>
where
K: fmt::Debug,
V: fmt::Debug,
usize: Into<K>,
{
#[allow(clippy::allow_attributes, reason = "rust-lang/rust#130021")]
#[allow(
clippy::missing_inline_in_public_items,
reason = "use default inlining behavior"
)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter_enumerated()).finish()
}
}
impl<K, V> AsRef<Self> for TiVec<K, V> {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl<K, V> AsMut<Self> for TiVec<K, V> {
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<K, V> AsRef<TiSlice<K, V>> for TiVec<K, V> {
#[inline]
fn as_ref(&self) -> &TiSlice<K, V> {
self
}
}
impl<K, V> AsMut<TiSlice<K, V>> for TiVec<K, V> {
#[inline]
fn as_mut(&mut self) -> &mut TiSlice<K, V> {
self
}
}
impl<K, V> AsRef<Vec<V>> for TiVec<K, V> {
#[inline]
fn as_ref(&self) -> &Vec<V> {
&self.raw
}
}
impl<K, V> AsMut<Vec<V>> for TiVec<K, V> {
#[inline]
fn as_mut(&mut self) -> &mut Vec<V> {
&mut self.raw
}
}
impl<K, V> AsRef<[V]> for TiVec<K, V> {
#[inline]
fn as_ref(&self) -> &[V] {
&self.raw
}
}
impl<K, V> AsMut<[V]> for TiVec<K, V> {
#[inline]
fn as_mut(&mut self) -> &mut [V] {
&mut self.raw
}
}
impl<K, V> AsRef<TiVec<K, V>> for Vec<V> {
#[inline]
fn as_ref(&self) -> &TiVec<K, V> {
TiVec::from_ref(self)
}
}
impl<K, V> AsMut<TiVec<K, V>> for Vec<V> {
#[inline]
fn as_mut(&mut self) -> &mut TiVec<K, V> {
TiVec::from_mut(self)
}
}
impl<K, V> Borrow<TiSlice<K, V>> for TiVec<K, V> {
#[inline]
fn borrow(&self) -> &TiSlice<K, V> {
self.as_slice()
}
}
impl<K, V> BorrowMut<TiSlice<K, V>> for TiVec<K, V> {
#[inline]
fn borrow_mut(&mut self) -> &mut TiSlice<K, V> {
self.as_mut_slice()
}
}
impl<K, V> Deref for TiVec<K, V> {
type Target = TiSlice<K, V>;
#[inline]
fn deref(&self) -> &TiSlice<K, V> {
Self::Target::from_ref(&self.raw)
}
}
impl<K, V> DerefMut for TiVec<K, V> {
#[inline]
fn deref_mut(&mut self) -> &mut TiSlice<K, V> {
Self::Target::from_mut(&mut self.raw)
}
}
impl<K, V> From<Vec<V>> for TiVec<K, V> {
#[inline]
fn from(vec: Vec<V>) -> Self {
Self {
raw: vec,
_marker: PhantomData,
}
}
}
impl<K, V> From<TiVec<K, V>> for Vec<V> {
#[inline]
fn from(vec: TiVec<K, V>) -> Self {
vec.raw
}
}
impl<K, V> From<&TiSlice<K, V>> for TiVec<K, V>
where
V: Clone,
{
#[inline]
fn from(slice: &TiSlice<K, V>) -> Self {
slice.to_vec()
}
}
impl<K, V> From<&mut TiSlice<K, V>> for TiVec<K, V>
where
V: Clone,
{
#[inline]
fn from(slice: &mut TiSlice<K, V>) -> Self {
slice.to_vec()
}
}
impl<K, V> From<Cow<'_, TiSlice<K, V>>> for TiVec<K, V>
where
V: Clone,
{
#[inline]
fn from(slice: Cow<'_, TiSlice<K, V>>) -> Self {
slice.into_owned()
}
}
impl<K, V> From<TiVec<K, V>> for Cow<'_, TiSlice<K, V>>
where
V: Clone,
{
#[inline]
fn from(vec: TiVec<K, V>) -> Self {
Cow::Owned(vec)
}
}
impl<K> From<&str> for TiVec<K, u8> {
#[inline]
fn from(s: &str) -> Self {
s.as_bytes().to_vec().into()
}
}
impl<K> From<String> for TiVec<K, u8> {
#[inline]
fn from(s: String) -> Self {
s.into_bytes().into()
}
}
impl<K> From<CString> for TiVec<K, u8> {
#[inline]
fn from(s: CString) -> Self {
s.into_bytes().into()
}
}
impl<K, V> Clone for TiVec<K, V>
where
V: Clone,
{
#[inline]
fn clone(&self) -> Self {
self.raw.clone().into()
}
}
impl<K, V> Eq for TiVec<K, V> where V: Eq {}
impl<K, A, B> PartialEq<TiVec<K, B>> for TiVec<K, A>
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &TiVec<K, B>) -> bool {
self.raw == other.raw
}
}
impl<K, A, B> PartialEq<TiSlice<K, B>> for TiVec<K, A>
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &TiSlice<K, B>) -> bool {
*self.raw == other.raw
}
}
impl<K, A, B> PartialEq<TiVec<K, B>> for TiSlice<K, A>
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &TiVec<K, B>) -> bool {
self.raw == *other.raw
}
}
impl<'a, K, A, B> PartialEq<&'a TiSlice<K, B>> for TiVec<K, A>
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&'a TiSlice<K, B>) -> bool {
*self.raw == other.raw
}
}
impl<K, A, B> PartialEq<TiVec<K, B>> for &TiSlice<K, A>
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &TiVec<K, B>) -> bool {
self.raw == *other.raw
}
}
impl<'a, K, A, B> PartialEq<&'a mut TiSlice<K, B>> for TiVec<K, A>
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &&'a mut TiSlice<K, B>) -> bool {
*self.raw == other.raw
}
}
impl<K, A, B> PartialEq<TiVec<K, B>> for &mut TiSlice<K, A>
where
A: PartialEq<B>,
{
#[inline]
fn eq(&self, other: &TiVec<K, B>) -> bool {
self.raw == *other.raw
}
}
impl<K, V> Ord for TiVec<K, V>
where
V: Ord,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.raw.cmp(&other.raw)
}
}
impl<K, V> PartialOrd<Self> for TiVec<K, V>
where
V: PartialOrd<V>,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.raw.partial_cmp(&other.raw)
}
}
impl<K, V> Hash for TiVec<K, V>
where
V: Hash,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.raw.hash(state);
}
}
impl<K, V> Default for TiVec<K, V> {
#[inline]
fn default() -> Self {
Vec::default().into()
}
}
impl<I, K, V> Index<I> for TiVec<K, V>
where
I: TiSliceIndex<K, V>,
{
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
index.index(self)
}
}
impl<I, K, V> IndexMut<I> for TiVec<K, V>
where
I: TiSliceIndex<K, V>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
index.index_mut(self)
}
}
impl<K, V> Extend<V> for TiVec<K, V> {
#[inline]
fn extend<I: IntoIterator<Item = V>>(&mut self, iter: I) {
self.raw.extend(iter);
}
}
impl<'a, K, V: 'a + Copy> Extend<&'a V> for TiVec<K, V> {
#[inline]
fn extend<I: IntoIterator<Item = &'a V>>(&mut self, iter: I) {
self.raw.extend(iter);
}
}
impl<K, V> FromIterator<V> for TiVec<K, V> {
#[inline]
fn from_iter<I: IntoIterator<Item = V>>(iter: I) -> Self {
Self {
raw: Vec::from_iter(iter),
_marker: PhantomData,
}
}
}
impl<K, V> IntoIterator for TiVec<K, V> {
type Item = V;
type IntoIter = vec::IntoIter<V>;
#[inline]
fn into_iter(self) -> vec::IntoIter<V> {
self.raw.into_iter()
}
}
impl<'a, K, V> IntoIterator for &'a TiVec<K, V> {
type Item = &'a V;
type IntoIter = slice::Iter<'a, V>;
#[inline]
fn into_iter(self) -> slice::Iter<'a, V> {
self.raw.iter()
}
}
impl<'a, K, V> IntoIterator for &'a mut TiVec<K, V> {
type Item = &'a mut V;
type IntoIter = slice::IterMut<'a, V>;
#[inline]
fn into_iter(self) -> slice::IterMut<'a, V> {
self.raw.iter_mut()
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<K> Write for TiVec<K, u8> {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
self.raw.write(buf)
}
#[inline]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> IoResult<usize> {
self.raw.write_vectored(bufs)
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
self.raw.write_all(buf)
}
#[inline]
fn flush(&mut self) -> IoResult<()> {
self.raw.flush()
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<K, V> Serialize for TiVec<K, V>
where
V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.raw.as_slice().serialize(serializer)
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de, K, V> Deserialize<'de> for TiVec<K, V>
where
V: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Vec::deserialize(deserializer).map(Into::into)
}
}
#[cfg(feature = "bincode")]
#[cfg_attr(docsrs, doc(cfg(feature = "bincode")))]
impl<K, V> Encode for TiVec<K, V>
where
V: Encode,
{
#[inline]
fn encode<E>(&self, encoder: &mut E) -> Result<(), EncodeError>
where
E: Encoder,
{
self.raw.encode(encoder)
}
}
#[cfg(feature = "bincode")]
#[cfg_attr(docsrs, doc(cfg(feature = "bincode")))]
impl<K, V, Context> Decode<Context> for TiVec<K, V>
where
V: Decode<Context>,
{
#[inline]
fn decode<D>(decoder: &mut D) -> Result<Self, DecodeError>
where
D: Decoder<Context = Context>,
{
Vec::decode(decoder).map(Into::into)
}
}
#[cfg(feature = "bincode")]
#[cfg_attr(docsrs, doc(cfg(feature = "bincode")))]
impl<'de, K, V, Context> BorrowDecode<'de, Context> for TiVec<K, V>
where
V: BorrowDecode<'de, Context>,
{
#[inline]
fn borrow_decode<D>(decoder: &mut D) -> Result<Self, DecodeError>
where
D: BorrowDecoder<'de, Context = Context>,
{
Vec::borrow_decode(decoder).map(Into::into)
}
}
#[expect(
dead_code,
unused_imports,
unused_mut,
clippy::into_iter_on_ref,
clippy::op_ref,
clippy::too_many_lines,
clippy::undocumented_unsafe_blocks,
clippy::unwrap_used,
reason = "okay in tests"
)]
#[cfg(test)]
mod test {
use alloc::borrow::{Cow, ToOwned};
use alloc::boxed::Box;
use alloc::ffi::CString;
use alloc::string::ToString;
use alloc::vec::Vec;
use core::borrow::{Borrow, BorrowMut};
use core::hash::{Hash, Hasher};
use core::ops::Bound;
#[cfg(feature = "std")]
use std::hash::DefaultHasher;
#[cfg(feature = "std")]
use std::io::{IoSlice, Write};
use crate::test_util::{AsSliceAndCapacity, Id};
use crate::{TiSlice, TiVec};
#[test]
fn test_vec_read_api_compatibility() {
assert_eq!(
TiVec::<Id, u32>::new().as_slice_and_capacity(),
Vec::<u32>::new().as_slice_and_capacity(),
);
for c in [0, 1, 2, 4] {
assert_eq!(
TiVec::<Id, u32>::with_capacity(c).as_slice_and_capacity(),
Vec::<u32>::with_capacity(c).as_slice_and_capacity(),
);
}
for v in [
&[0_u32; 0][..],
&[1],
&[1, 1234],
&[1, 2, 4],
&[1, 5, 3, 2],
&[1, 1, 9, 2, 4, 1, 12345, 12],
] {
let cv = (v.to_vec(), TiVec::<Id, _>::from(v.to_vec()));
let mut cv = (&cv.0, &cv.1);
let mut mv = (v.to_vec(), TiVec::<Id, _>::from(v.to_vec()));
let mut mv = (&mut mv.0, &mut mv.1);
assert_eq_api!(cv, v => AsRef::<[_]>::as_ref(v));
assert_eq_api!(mv, v => AsMut::<[_]>::as_mut(v));
assert_eq_api!(cv, v => AsRef::<Vec<_>>::as_ref(v));
assert_eq_api!(mv, v => AsMut::<Vec<_>>::as_mut(v));
assert_eq_api!(cv, v => AsRef::<TiVec<_, _>>::as_ref(v));
assert_eq_api!(mv, v => AsMut::<TiVec<_, _>>::as_mut(v));
assert_eq!(
AsRef::<[_]>::as_ref(cv.0),
AsRef::<[_]>::as_ref(AsRef::<TiSlice<_, _>>::as_ref(cv.1))
);
assert_eq!(
AsMut::<[_]>::as_mut(mv.0),
AsMut::<[_]>::as_mut(AsMut::<TiSlice<_, _>>::as_mut(mv.1))
);
assert_eq!(
Borrow::<[_]>::borrow(cv.0),
AsRef::<[_]>::as_ref(Borrow::<TiSlice<_, _>>::borrow(cv.1))
);
assert_eq!(
BorrowMut::<[_]>::borrow_mut(mv.0),
AsMut::<[_]>::as_mut(BorrowMut::<TiSlice<_, _>>::borrow_mut(mv.1))
);
assert_eq_api!(cv, v => v.len());
assert_eq_api!(cv, v => v.is_empty());
assert_eq_api!(cv, v => v.capacity());
assert_eq_api!(cv, v => v.as_slice().into_std());
assert_eq_api!(mv, v => v.as_mut_slice().into_std());
assert_eq_api!(cv, v => TheVec::from(v.as_slice()).into_std());
assert_eq_api!(mv, v => TheVec::from(v.as_mut_slice()).into_std());
assert_eq_api!(cv, v => TheVec::from(Cow::Borrowed(v.as_slice())).into_std());
assert_eq_api!(mv, v => Cow::from(v.clone()).into_std());
if !v.is_empty() {
assert_ne!(cv.0.as_ptr(), cv.1.as_ptr());
assert_ne!(cv.0.as_ptr_range(), cv.1.as_ptr_range());
assert_ne!(mv.0.as_mut_ptr(), mv.1.as_mut_ptr());
assert_ne!(mv.0.as_mut_ptr_range(), mv.1.as_mut_ptr_range());
}
assert_eq_api!(cv, v => *v == TheVec::<u32>::default());
assert_eq_api!(cv, v => v == v.as_slice());
assert_eq_api!(cv, v => v.as_slice() == v);
assert_eq_api!(cv, v => v == &v.as_slice());
assert_eq_api!(cv, v => &v.as_slice() == v);
assert_eq_api!(mv, v => v == &(&mut [1_u32, 1234][..]).into_tic());
assert_eq_api!(mv, v => &(&mut [1_u32, 1234][..]).into_tic() == v);
assert_eq_api!(cv, v => v.cmp(&alloc::vec![1, 1234].into_tic()));
assert_eq_api!(cv, v => v.partial_cmp(&alloc::vec![1, 1234].into_tic()));
for i in 0..v.len() {
assert_eq_api!(cv, v => v[i.into_tic()]);
assert_eq_api!(mv, v => v[i.into_tic()] = v[i.into_tic()]);
}
unsafe {
assert_eq_api!(cv, v => {
let mut v = core::mem::ManuallyDrop::new(v.clone());
TheVec::from_raw_parts(v.as_mut_ptr(), v.len(), v.capacity()).into_std()
});
}
}
}
#[test]
fn test_vec_write_api_compatibility() {
for v in [
&[0_u32; 0][..],
&[1],
&[1, 1234],
&[1, 2, 4],
&[1, 5, 3, 2],
&[1, 1, 9, 2, 4, 1, 12345, 12],
] {
let mut mv = (v.to_vec(), TiVec::<Id, _>::from(v.to_vec()));
let mut mv = (&mut mv.0, &mut mv.1);
let restore = |mv: &mut (&mut Vec<u32>, &mut TiVec<Id, u32>)| {
*mv.0 = v.to_vec();
*mv.1 = TiVec::from(v.to_vec());
};
restore(&mut mv);
assert_eq_api!(mv, v => v.try_reserve(usize::MAX));
restore(&mut mv);
assert_eq_api!(mv, v => v.try_reserve_exact(usize::MAX));
for i in 0..8 {
restore(&mut mv);
assert_eq_api!(mv, v => v.resize(i, 123));
restore(&mut mv);
assert_eq_api!(mv, v => { let mut a = 1; v.resize_with(i, || { a *= 2; a }) });
restore(&mut mv);
assert_eq_api!(mv, v => v.reserve(i));
assert_eq_api!(mv, v => v.spare_capacity_mut().len());
restore(&mut mv);
assert_eq_api!(mv, v => v.try_reserve(i));
restore(&mut mv);
assert_eq_api!(mv, v => v.reserve_exact(i));
restore(&mut mv);
assert_eq_api!(mv, v => v.try_reserve_exact(i));
restore(&mut mv);
assert_eq_api!(mv, v => v.reserve_exact(i));
assert_eq_api!(mv, v => v.shrink_to_fit());
restore(&mut mv);
assert_eq_api!(mv, v => v.reserve_exact(i * 2));
assert_eq_api!(mv, v => v.shrink_to(i));
restore(&mut mv);
assert_eq_api!(mv, v => v.truncate(i));
}
let l1: Vec<_> = mv.0.clone();
let l1c = l1.capacity();
let l1 = l1.leak();
let l2: TiVec<_, _> = mv.1.clone();
let l2c = l2.capacity();
let l2 = l2.leak();
assert_eq!(l1, &l2.raw);
drop(unsafe { Vec::from_raw_parts(l1.as_mut_ptr(), l1.len(), l1c) });
drop(unsafe { TiVec::<Id, _>::from_raw_parts(l2.as_mut_ptr(), l2.len(), l2c) });
restore(&mut mv);
assert_eq_api!(mv, v => (&*v).into_iter().copied().collect::<Vec<_>>());
assert_eq_api!(mv, v => v.iter_mut().collect::<Vec<_>>());
assert_eq_api!(mv, v => v.clone().into_iter().collect::<Vec<_>>());
restore(&mut mv);
assert_eq_api!(mv, v => v.pop());
assert_eq_api!(mv, v => v.push(123));
assert_eq_api!(mv, v => v.pop());
restore(&mut mv);
assert_eq_api!(mv, v => v.pop_if(|v| *v < 10));
assert_eq_api!(mv, v => v.push(234));
restore(&mut mv);
assert_eq_api!(mv, v => v.append(&mut v.clone()));
restore(&mut mv);
assert_eq_api!(mv, v => v.extend(v.clone().as_slice()));
restore(&mut mv);
assert_eq_api!(mv, v => v.extend(v.clone().iter().copied()));
restore(&mut mv);
assert_eq_api!(mv, v => v.extend_from_slice(&v.clone()));
restore(&mut mv);
assert_eq_api!(mv, v => v.into_iter().collect::<TheVec<_>>().into_std());
restore(&mut mv);
assert_eq_api!(mv, v => v.retain(|value| value % 3 == 0 || value % 4 == 0));
restore(&mut mv);
assert_eq_api!(mv, v => v.retain_mut(|value| {
*value += 1;
*value % 3 == 0 || *value % 4 == 0
}));
restore(&mut mv);
assert_eq_api!(mv, v => v.dedup());
restore(&mut mv);
assert_eq_api!(mv, v => v.dedup_by(|lhs, rhs| lhs < rhs));
restore(&mut mv);
assert_eq_api!(mv, v => v.dedup_by_key(|value| *value % 3));
for i in 0..v.len() {
restore(&mut mv);
assert_eq_api!(mv, v => v.swap_remove(i.into_tic()));
restore(&mut mv);
assert_eq_api!(mv, v => v.insert(i.into_tic(), 123));
restore(&mut mv);
assert_eq_api!(mv, v => v.remove(i.into_tic()));
restore(&mut mv);
unsafe { assert_eq_api!(mv, v => v.set_len(i)) };
restore(&mut mv);
assert_eq_api!(mv, v => v.split_off(i.into_tic()).into_std());
}
for a in 0..v.len() {
for b in a..v.len() {
restore(&mut mv);
assert_eq_api!(mv, v => v.drain((a..b).into_tic()).collect::<Vec<_>>());
restore(&mut mv);
assert_eq_api!(mv, v => v.extend_from_within(a..b));
restore(&mut mv);
assert_eq_api!(
mv, v => v.splice((a..b).into_tic(), [1, 2, 3]).collect::<Vec<_>>()
);
}
}
restore(&mut mv);
assert_eq_api!(mv, v => v.splice(.., [1, 2, 3]).collect::<Vec<_>>());
restore(&mut mv);
assert_eq_api!(mv, v => v.clear());
}
}
#[cfg(feature = "std")]
#[test]
fn test_vec_hash_compatibility() {
for v in [
&[0_u32; 0][..],
&[1],
&[1, 1234],
&[1, 2, 4],
&[1, 5, 3, 2],
&[1, 1, 9, 2, 4, 1, 12345, 12],
] {
let cv = (v.to_vec(), TiVec::<Id, _>::from(v.to_vec()));
let mut cv = (&cv.0, &cv.1);
assert_eq_api!(cv, v => {
let mut hasher = DefaultHasher::new();
v.hash(&mut hasher);
hasher.finish()
});
}
}
#[test]
fn test_u8_vec_api_compatibility() {
assert_eq!(
Vec::from(TiVec::<Id, u8>::from("abc")),
Vec::<u8>::from("abc"),
);
assert_eq!(
Vec::from(TiVec::<Id, u8>::from("abc".to_owned())),
Vec::<u8>::from("abc".to_owned()),
);
assert_eq!(
Vec::from(TiVec::<Id, u8>::from(CString::new("abc").unwrap())),
Vec::<u8>::from(CString::new("abc").unwrap()),
);
for v in [&b"abc"[..], b"aBc", b"ABC", b"abd", b"a\x80\x81b"] {
let cv = (v.to_vec(), TiVec::<Id, _>::from(v.to_vec()));
let mut cv = (&cv.0, &cv.1);
assert_eq_api!(cv, v => TheVec::from(v.as_slice()).into_std());
}
}
#[test]
fn test_vec_debug() {
let s0: TiVec<Id, u32> = TiVec::from(alloc::vec![]);
let s1: TiVec<Id, u32> = TiVec::from(alloc::vec![12]);
let s2: TiVec<Id, u32> = TiVec::from(alloc::vec![23, 34]);
assert_eq!(&alloc::format!("{s0:?}"), "{}");
assert_eq!(&alloc::format!("{s1:?}"), "{Id(0): 12}");
assert_eq!(&alloc::format!("{s2:?}"), "{Id(0): 23, Id(1): 34}");
}
#[cfg(feature = "std")]
#[test]
fn test_vec_write() {
let mut mv = (Vec::<u8>::new(), TiVec::<Id, u8>::new());
let mut mv = (&mut mv.0, &mut mv.1);
assert_eq_api!(mv, v => v.write(&[1, 2, 3]).unwrap());
assert_eq_api!(mv, v => v.write_vectored(
&[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5])]
).unwrap());
assert_eq_api!(mv, v => v.write_all(&[1, 2, 3]).unwrap());
assert_eq_api!(mv, v => v.flush().unwrap());
}
#[cfg(feature = "serde")]
#[test]
fn test_vec_serialize() {
let s0: TiVec<Id, u32> = TiVec::from(alloc::vec![]);
let s1: TiVec<Id, u32> = TiVec::from(alloc::vec![12]);
let s2: TiVec<Id, u32> = TiVec::from(alloc::vec![23, 34]);
assert_eq!(&serde_json::to_string(&s0).unwrap(), "[]");
assert_eq!(&serde_json::to_string(&s1).unwrap(), "[12]");
assert_eq!(&serde_json::to_string(&s2).unwrap(), "[23,34]");
}
#[cfg(feature = "serde")]
#[test]
fn test_vec_deserialize() {
let s0: TiVec<Id, u32> = serde_json::from_str("[]").unwrap();
let s1: TiVec<Id, u32> = serde_json::from_str("[12]").unwrap();
let s2: TiVec<Id, u32> = serde_json::from_str("[23, 34]").unwrap();
assert_eq!(s0.as_slice().raw, [0; 0][..]);
assert_eq!(s1.as_slice().raw, [12][..]);
assert_eq!(s2.as_slice().raw, [23, 34][..]);
}
#[cfg(feature = "bincode")]
#[test]
fn test_vec_encode() {
let config = bincode::config::standard();
let s0: TiVec<Id, u32> = TiVec::from(alloc::vec![]);
let s1: TiVec<Id, u32> = TiVec::from(alloc::vec![12]);
let s2: TiVec<Id, u32> = TiVec::from(alloc::vec![23, 34]);
let s3: TiVec<Id, u32> = TiVec::from(alloc::vec![0x1234_5678, 0x2345_6789]);
assert_eq!(&bincode::encode_to_vec(s0, config).unwrap(), &[0]);
assert_eq!(&bincode::encode_to_vec(s1, config).unwrap(), &[1, 12]);
assert_eq!(&bincode::encode_to_vec(s2, config).unwrap(), &[2, 23, 34]);
assert_eq!(
&bincode::encode_to_vec(s3, config).unwrap(),
&[2, 252, 0x78, 0x56, 0x34, 0x12, 252, 0x89, 0x67, 0x45, 0x23]
);
}
#[cfg(feature = "bincode")]
#[test]
fn test_vec_decode() {
fn decode_whole(bytes: &[u8]) -> TiVec<Id, u32> {
let config = bincode::config::standard();
let (decoded, len) = bincode::decode_from_slice(bytes, config).unwrap();
assert_eq!(len, bytes.len());
decoded
}
let s0: TiVec<Id, u32> = decode_whole(&[0]);
let s1: TiVec<Id, u32> = decode_whole(&[1, 12]);
let s2: TiVec<Id, u32> = decode_whole(&[2, 23, 34]);
let s3: TiVec<Id, u32> =
decode_whole(&[2, 252, 0x78, 0x56, 0x34, 0x12, 252, 0x89, 0x67, 0x45, 0x23]);
assert_eq!(s0.as_slice().raw, [0; 0][..]);
assert_eq!(s1.as_slice().raw, [12][..]);
assert_eq!(s2.as_slice().raw, [23, 34][..]);
assert_eq!(s3.as_slice().raw, [0x1234_5678, 0x2345_6789][..]);
}
#[cfg(feature = "bincode")]
#[test]
fn test_boxed_slice_borrow_decode() {
fn decode_whole(bytes: &[u8]) -> TiVec<Id, &str> {
let config = bincode::config::standard();
let (decoded, len) = bincode::borrow_decode_from_slice(bytes, config).unwrap();
assert_eq!(len, bytes.len());
decoded
}
let s0: TiVec<Id, &str> = decode_whole(&[0]);
let s1: TiVec<Id, &str> = decode_whole(&[1, 1, b'a']);
let s2: TiVec<Id, &str> = decode_whole(&[2, 2, b'b', b'c', 3, b'd', b'e', b'f']);
assert_eq!(s0.as_slice().raw, [""; 0][..]);
assert_eq!(s1.as_slice().raw, ["a"][..]);
assert_eq!(s2.as_slice().raw, ["bc", "def"][..]);
}
}