use core::{
borrow::Borrow,
cmp::Ordering,
convert::Infallible,
fmt::Debug,
iter::FusedIterator,
marker::PhantomData,
ops::{Bound, RangeBounds},
};
use crate::{
iter::{UnwrappedEnumerable, UnwrappedIter},
unwrap::{UnwrapInfallible, UnwrapOptimized},
};
use super::{
env::internal::{Env as _, EnvBase as _, VecObject},
ConversionError, Env, IntoVal, TryFromVal, TryIntoVal, Val,
};
#[cfg(doc)]
use crate::{storage::Storage, Bytes, BytesN, Map};
#[macro_export]
macro_rules! vec {
($env:expr $(,)?) => {
$crate::Vec::new($env)
};
($env:expr, $($x:expr),+ $(,)?) => {
$crate::Vec::from_array($env, [$($x),+])
};
}
pub struct Vec<T> {
env: Env,
obj: VecObject,
_t: PhantomData<T>,
}
impl<T> Clone for Vec<T> {
fn clone(&self) -> Self {
Self {
env: self.env.clone(),
obj: self.obj,
_t: self._t,
}
}
}
impl<T> Eq for Vec<T> where T: IntoVal<Env, Val> + TryFromVal<Env, Val> {}
impl<T> PartialEq for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(Ordering::Equal)
}
}
impl<T> PartialOrd for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(Ord::cmp(self, other))
}
}
impl<T> Ord for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.env.check_same_env(&other.env).unwrap_infallible();
let v = self
.env
.obj_cmp(self.obj.to_val(), other.obj.to_val())
.unwrap_infallible();
v.cmp(&0)
}
}
impl<T> Debug for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val> + Debug + Clone,
T::Error: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Vec(")?;
let mut iter = self.try_iter();
if let Some(x) = iter.next() {
write!(f, "{:?}", x)?;
}
for x in iter {
write!(f, ", {:?}", x)?;
}
write!(f, ")")?;
Ok(())
}
}
impl<T> TryFromVal<Env, Vec<T>> for Vec<Val> {
type Error = Infallible;
fn try_from_val(env: &Env, v: &Vec<T>) -> Result<Self, Self::Error> {
Ok(unsafe { Vec::unchecked_new(env.clone(), v.obj) })
}
}
impl<T> TryFromVal<Env, &Vec<Val>> for Vec<T> {
type Error = Infallible;
fn try_from_val(env: &Env, v: &&Vec<Val>) -> Result<Self, Self::Error> {
Ok(unsafe { Vec::unchecked_new(env.clone(), v.obj) })
}
}
impl<T> TryFromVal<Env, VecObject> for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Error = Infallible;
#[inline(always)]
fn try_from_val(env: &Env, obj: &VecObject) -> Result<Self, Self::Error> {
Ok(unsafe { Vec::<T>::unchecked_new(env.clone(), *obj) })
}
}
impl<T> TryFromVal<Env, Val> for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Error = ConversionError;
#[inline(always)]
fn try_from_val(env: &Env, val: &Val) -> Result<Self, Self::Error> {
Ok(VecObject::try_from_val(env, val)?
.try_into_val(env)
.unwrap_infallible())
}
}
impl<T> TryFromVal<Env, Vec<T>> for Val {
type Error = ConversionError;
fn try_from_val(_env: &Env, v: &Vec<T>) -> Result<Self, Self::Error> {
Ok(v.to_val())
}
}
impl<T> From<Vec<T>> for Val
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
#[inline(always)]
fn from(v: Vec<T>) -> Self {
v.obj.into()
}
}
impl<T> From<Vec<T>> for VecObject
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
#[inline(always)]
fn from(v: Vec<T>) -> Self {
v.obj
}
}
#[cfg(not(target_family = "wasm"))]
use super::xdr::{ScVal, ScVec, VecM};
#[cfg(not(target_family = "wasm"))]
impl<T> From<&Vec<T>> for ScVal {
fn from(v: &Vec<T>) -> Self {
ScVal::try_from_val(&v.env, &v.obj.to_val()).unwrap()
}
}
#[cfg(not(target_family = "wasm"))]
impl<T> From<&Vec<T>> for ScVec {
fn from(v: &Vec<T>) -> Self {
if let ScVal::Vec(Some(vec)) = ScVal::try_from(v).unwrap() {
vec
} else {
panic!("expected ScVec")
}
}
}
#[cfg(not(target_family = "wasm"))]
impl<T> From<Vec<T>> for VecM<ScVal> {
fn from(v: Vec<T>) -> Self {
ScVec::from(v).0
}
}
#[cfg(not(target_family = "wasm"))]
impl<T> From<Vec<T>> for ScVal {
fn from(v: Vec<T>) -> Self {
(&v).into()
}
}
#[cfg(not(target_family = "wasm"))]
impl<T> From<Vec<T>> for ScVec {
fn from(v: Vec<T>) -> Self {
(&v).into()
}
}
#[cfg(not(target_family = "wasm"))]
impl<T> TryFromVal<Env, ScVal> for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Error = ConversionError;
fn try_from_val(env: &Env, val: &ScVal) -> Result<Self, ConversionError> {
Ok(VecObject::try_from_val(env, &Val::try_from_val(env, val)?)?
.try_into_val(env)
.unwrap_infallible())
}
}
#[cfg(not(target_family = "wasm"))]
impl<T> TryFromVal<Env, ScVec> for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Error = ConversionError;
fn try_from_val(env: &Env, val: &ScVec) -> Result<Self, Self::Error> {
ScVal::Vec(Some(val.clone())).try_into_val(env)
}
}
#[cfg(not(target_family = "wasm"))]
impl<T> TryFromVal<Env, VecM<ScVal>> for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Error = ConversionError;
fn try_from_val(env: &Env, val: &VecM<ScVal>) -> Result<Self, Self::Error> {
ScVec(val.clone()).try_into_val(env)
}
}
impl<T> Vec<T> {
#[inline(always)]
pub(crate) unsafe fn unchecked_new(env: Env, obj: VecObject) -> Self {
Self {
env,
obj,
_t: PhantomData,
}
}
pub fn env(&self) -> &Env {
&self.env
}
pub fn as_val(&self) -> &Val {
self.obj.as_val()
}
pub fn to_val(&self) -> Val {
self.obj.to_val()
}
pub fn as_object(&self) -> &VecObject {
&self.obj
}
pub fn to_object(&self) -> VecObject {
self.obj
}
pub fn to_vals(&self) -> Vec<Val> {
unsafe { Vec::<Val>::unchecked_new(self.env().clone(), self.obj) }
}
}
impl<T> Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
#[inline(always)]
pub fn new(env: &Env) -> Vec<T> {
unsafe { Self::unchecked_new(env.clone(), env.vec_new().unwrap_infallible()) }
}
#[inline(always)]
pub fn from_array<const N: usize>(env: &Env, items: [T; N]) -> Vec<T> {
let mut tmp: [Val; N] = [Val::VOID.to_val(); N];
for (dst, src) in tmp.iter_mut().zip(items.iter()) {
*dst = src.into_val(env)
}
let vec = env.vec_new_from_slice(&tmp).unwrap_infallible();
unsafe { Self::unchecked_new(env.clone(), vec) }
}
#[inline(always)]
pub fn from_slice(env: &Env, items: &[T]) -> Vec<T>
where
T: Clone,
{
let mut vec = Vec::new(env);
vec.extend_from_slice(items);
vec
}
#[inline(always)]
pub fn get(&self, i: u32) -> Option<T> {
self.try_get(i).unwrap_optimized()
}
#[inline(always)]
pub fn try_get(&self, i: u32) -> Result<Option<T>, T::Error> {
if i < self.len() {
self.try_get_unchecked(i).map(|val| Some(val))
} else {
Ok(None)
}
}
#[inline(always)]
pub fn get_unchecked(&self, i: u32) -> T {
self.try_get_unchecked(i).unwrap_optimized()
}
#[inline(always)]
pub fn try_get_unchecked(&self, i: u32) -> Result<T, T::Error> {
let env = self.env();
let val = env.vec_get(self.obj, i.into()).unwrap_infallible();
T::try_from_val(env, &val)
}
#[inline(always)]
pub fn set(&mut self, i: u32, v: T) {
let env = self.env();
self.obj = env
.vec_put(self.obj, i.into(), v.into_val(env))
.unwrap_infallible();
}
#[inline(always)]
pub fn remove(&mut self, i: u32) -> Option<()> {
if i < self.len() {
self.remove_unchecked(i);
Some(())
} else {
None
}
}
#[inline(always)]
pub fn remove_unchecked(&mut self, i: u32) {
let env = self.env();
self.obj = env.vec_del(self.obj, i.into()).unwrap_infallible();
}
#[inline(always)]
pub fn push_front(&mut self, x: T) {
let env = self.env();
self.obj = env
.vec_push_front(self.obj, x.into_val(env))
.unwrap_infallible();
}
#[inline(always)]
pub fn pop_front(&mut self) -> Option<T> {
self.try_pop_front().unwrap_optimized()
}
#[inline(always)]
pub fn try_pop_front(&mut self) -> Result<Option<T>, T::Error> {
if self.is_empty() {
Ok(None)
} else {
self.try_pop_front_unchecked().map(|val| Some(val))
}
}
#[inline(always)]
pub fn pop_front_unchecked(&mut self) -> T {
self.try_pop_front_unchecked().unwrap_optimized()
}
#[inline(always)]
pub fn try_pop_front_unchecked(&mut self) -> Result<T, T::Error> {
let last = self.try_first_unchecked()?;
let env = self.env();
self.obj = env.vec_pop_front(self.obj).unwrap_infallible();
Ok(last)
}
#[inline(always)]
pub fn push_back(&mut self, x: T) {
let env = self.env();
self.obj = env
.vec_push_back(self.obj, x.into_val(env))
.unwrap_infallible();
}
#[inline(always)]
pub fn pop_back(&mut self) -> Option<T> {
self.try_pop_back().unwrap_optimized()
}
#[inline(always)]
pub fn try_pop_back(&mut self) -> Result<Option<T>, T::Error> {
if self.is_empty() {
Ok(None)
} else {
self.try_pop_back_unchecked().map(|val| Some(val))
}
}
#[inline(always)]
pub fn pop_back_unchecked(&mut self) -> T {
self.try_pop_back_unchecked().unwrap_optimized()
}
#[inline(always)]
pub fn try_pop_back_unchecked(&mut self) -> Result<T, T::Error> {
let last = self.try_last_unchecked()?;
let env = self.env();
self.obj = env.vec_pop_back(self.obj).unwrap_infallible();
Ok(last)
}
#[inline(always)]
pub fn first(&self) -> Option<T> {
self.try_first().unwrap_optimized()
}
#[inline(always)]
pub fn try_first(&self) -> Result<Option<T>, T::Error> {
if self.is_empty() {
Ok(None)
} else {
self.try_first_unchecked().map(|val| Some(val))
}
}
#[inline(always)]
pub fn first_unchecked(&self) -> T {
self.try_first_unchecked().unwrap_optimized()
}
#[inline(always)]
pub fn try_first_unchecked(&self) -> Result<T, T::Error> {
let env = &self.env;
let val = env.vec_front(self.obj).unwrap_infallible();
T::try_from_val(env, &val)
}
#[inline(always)]
pub fn last(&self) -> Option<T> {
self.try_last().unwrap_optimized()
}
#[inline(always)]
pub fn try_last(&self) -> Result<Option<T>, T::Error> {
if self.is_empty() {
Ok(None)
} else {
self.try_last_unchecked().map(|val| Some(val))
}
}
#[inline(always)]
pub fn last_unchecked(&self) -> T {
self.try_last_unchecked().unwrap_optimized()
}
#[inline(always)]
pub fn try_last_unchecked(&self) -> Result<T, T::Error> {
let env = self.env();
let val = env.vec_back(self.obj).unwrap_infallible();
T::try_from_val(env, &val)
}
#[inline(always)]
pub fn insert(&mut self, i: u32, x: T) {
let env = self.env();
self.obj = env
.vec_insert(self.obj, i.into(), x.into_val(env))
.unwrap_infallible();
}
#[inline(always)]
pub fn append(&mut self, other: &Vec<T>) {
let env = self.env();
self.obj = env.vec_append(self.obj, other.obj).unwrap_infallible();
}
#[inline(always)]
pub fn extend_from_array<const N: usize>(&mut self, items: [T; N]) {
self.append(&Self::from_array(&self.env, items))
}
#[inline(always)]
pub fn extend_from_slice(&mut self, items: &[T])
where
T: Clone,
{
for item in items {
self.push_back(item.clone());
}
}
}
impl<T> Vec<T> {
#[must_use]
pub fn slice(&self, r: impl RangeBounds<u32>) -> Self {
let start_bound = match r.start_bound() {
Bound::Included(s) => *s,
Bound::Excluded(s) => *s + 1,
Bound::Unbounded => 0,
};
let end_bound = match r.end_bound() {
Bound::Included(s) => *s + 1,
Bound::Excluded(s) => *s,
Bound::Unbounded => self.len(),
};
let env = self.env();
let obj = env
.vec_slice(self.obj, start_bound.into(), end_bound.into())
.unwrap_infallible();
unsafe { Self::unchecked_new(env.clone(), obj) }
}
pub fn shuffle(&mut self) {
let env = self.env();
env.prng().shuffle(self);
}
#[must_use]
pub fn to_shuffled(&self) -> Self {
let mut copy = self.clone();
copy.shuffle();
copy
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline(always)]
pub fn len(&self) -> u32 {
self.env.vec_len(self.obj).unwrap_infallible().into()
}
}
impl<T> Vec<T>
where
T: IntoVal<Env, Val>,
{
#[inline(always)]
pub fn contains(&self, item: impl Borrow<T>) -> bool {
let env = self.env();
let val = item.borrow().into_val(env);
!env.vec_first_index_of(self.obj, val)
.unwrap_infallible()
.is_void()
}
#[inline(always)]
pub fn first_index_of(&self, item: impl Borrow<T>) -> Option<u32> {
let env = self.env();
let val = item.borrow().into_val(env);
env.vec_first_index_of(self.obj, val)
.unwrap_infallible()
.try_into_val(env)
.unwrap()
}
#[inline(always)]
pub fn last_index_of(&self, item: impl Borrow<T>) -> Option<u32> {
let env = self.env();
let val = item.borrow().into_val(env);
env.vec_last_index_of(self.obj, val)
.unwrap_infallible()
.try_into_val(env)
.unwrap()
}
#[inline(always)]
pub fn binary_search(&self, item: impl Borrow<T>) -> Result<u32, u32> {
let env = self.env();
let val = item.borrow().into_val(env);
let high_low = env.vec_binary_search(self.obj, val).unwrap_infallible();
let high: u32 = (high_low >> u32::BITS) as u32;
let low: u32 = high_low as u32;
if high == 1 {
Ok(low)
} else {
Err(low)
}
}
}
impl<T> Vec<Vec<T>>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
T: Clone,
{
#[inline(always)]
pub fn concat(&self) -> Vec<T> {
let mut concatenated = vec![self.env()];
for vec in self.iter() {
concatenated.append(&vec);
}
concatenated
}
}
impl<T> IntoIterator for Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Item = T;
type IntoIter = UnwrappedIter<VecTryIter<T>, T, T::Error>;
fn into_iter(self) -> Self::IntoIter {
VecTryIter::new(self).unwrapped()
}
}
impl<T> IntoIterator for &Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Item = T;
type IntoIter = UnwrappedIter<VecTryIter<T>, T, T::Error>;
fn into_iter(self) -> Self::IntoIter {
self.clone().into_iter()
}
}
impl<T> Vec<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
#[inline(always)]
pub fn iter(&self) -> UnwrappedIter<VecTryIter<T>, T, T::Error>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val> + Clone,
T::Error: Debug,
{
self.try_iter().unwrapped()
}
#[inline(always)]
pub fn try_iter(&self) -> VecTryIter<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val> + Clone,
{
VecTryIter::new(self.clone())
}
#[inline(always)]
pub fn into_try_iter(self) -> VecTryIter<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val> + Clone,
T::Error: Debug,
{
VecTryIter::new(self.clone())
}
}
#[derive(Clone)]
pub struct VecTryIter<T> {
vec: Vec<T>,
start: u32, end: u32, }
impl<T> VecTryIter<T> {
fn new(vec: Vec<T>) -> Self {
Self {
start: 0,
end: vec.len(),
vec,
}
}
fn into_vec(self) -> Vec<T> {
self.vec.slice(self.start..self.end)
}
}
impl<T> Iterator for VecTryIter<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
type Item = Result<T, T::Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.start < self.end {
let val = self.vec.try_get_unchecked(self.start);
self.start += 1;
Some(val)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = (self.end - self.start) as usize;
(len, Some(len))
}
}
impl<T> DoubleEndedIterator for VecTryIter<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.start < self.end {
let val = self.vec.try_get_unchecked(self.end - 1);
self.end -= 1;
Some(val)
} else {
None
}
}
}
impl<T> FusedIterator for VecTryIter<T> where T: IntoVal<Env, Val> + TryFromVal<Env, Val> {}
impl<T> ExactSizeIterator for VecTryIter<T>
where
T: IntoVal<Env, Val> + TryFromVal<Env, Val>,
{
fn len(&self) -> usize {
(self.end - self.start) as usize
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_vec_macro() {
let env = Env::default();
assert_eq!(vec![&env], Vec::<i32>::new(&env));
assert_eq!(vec![&env,], Vec::<i32>::new(&env));
assert_eq!(vec![&env, 1], {
let mut v = Vec::new(&env);
v.push_back(1);
v
});
assert_eq!(vec![&env, 1,], {
let mut v = Vec::new(&env);
v.push_back(1);
v
});
assert_eq!(vec![&env, 3, 2, 1,], {
let mut v = Vec::new(&env);
v.push_back(3);
v.push_back(2);
v.push_back(1);
v
});
}
#[test]
fn test_vec_raw_val_type() {
let env = Env::default();
let mut vec = Vec::<u32>::new(&env);
assert_eq!(vec.len(), 0);
vec.push_back(10);
assert_eq!(vec.len(), 1);
vec.push_back(20);
assert_eq!(vec.len(), 2);
vec.push_back(30);
assert_eq!(vec.len(), 3);
let vec_ref = &vec;
assert_eq!(vec_ref.len(), 3);
let mut vec_copy = vec.clone();
assert!(vec == vec_copy);
assert_eq!(vec_copy.len(), 3);
vec_copy.push_back(40);
assert_eq!(vec_copy.len(), 4);
assert!(vec != vec_copy);
assert_eq!(vec.len(), 3);
assert_eq!(vec_ref.len(), 3);
_ = vec_copy.pop_back_unchecked();
assert!(vec == vec_copy);
}
#[test]
fn test_vec_env_val_type() {
let env = Env::default();
let mut vec = Vec::<i64>::new(&env);
assert_eq!(vec.len(), 0);
vec.push_back(-10);
assert_eq!(vec.len(), 1);
vec.push_back(20);
assert_eq!(vec.len(), 2);
vec.push_back(-30);
assert_eq!(vec.len(), 3);
let vec_ref = &vec;
assert_eq!(vec_ref.len(), 3);
let mut vec_copy = vec.clone();
assert!(vec == vec_copy);
assert_eq!(vec_copy.len(), 3);
vec_copy.push_back(40);
assert_eq!(vec_copy.len(), 4);
assert!(vec != vec_copy);
assert_eq!(vec.len(), 3);
assert_eq!(vec_ref.len(), 3);
_ = vec_copy.pop_back_unchecked();
assert!(vec == vec_copy);
}
#[test]
fn test_vec_to_vals() {
let env = Env::default();
let vec = vec![&env, 0, 1, 2, 3, 4];
let vals = vec.to_vals();
assert_eq!(
vals,
vec![
&env,
Val::from_i32(0).to_val(),
Val::from_i32(1).to_val(),
Val::from_i32(2).to_val(),
Val::from_i32(3).to_val(),
Val::from_i32(4).to_val(),
]
);
}
#[test]
fn test_vec_recursive() {
let env = Env::default();
let mut vec_inner = Vec::<i64>::new(&env);
vec_inner.push_back(-10);
assert_eq!(vec_inner.len(), 1);
let mut vec_outer = Vec::<Vec<i64>>::new(&env);
vec_outer.push_back(vec_inner);
assert_eq!(vec_outer.len(), 1);
}
#[test]
fn test_vec_concat() {
let env = Env::default();
let vec_1: Vec<i64> = vec![&env, 1, 2, 3];
let vec_2: Vec<i64> = vec![&env, 4, 5, 6];
let vec = vec![&env, vec_1, vec_2].concat();
assert_eq!(vec, vec![&env, 1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_vec_slice() {
let env = Env::default();
let vec = vec![&env, 0, 1, 2, 3, 4];
assert_eq!(vec.len(), 5);
let slice = vec.slice(..);
assert_eq!(slice, vec![&env, 0, 1, 2, 3, 4]);
let slice = vec.slice(0..5);
assert_eq!(slice, vec![&env, 0, 1, 2, 3, 4]);
let slice = vec.slice(0..=4);
assert_eq!(slice, vec![&env, 0, 1, 2, 3, 4]);
let slice = vec.slice(1..);
assert_eq!(slice, vec![&env, 1, 2, 3, 4]);
let slice = vec.slice(..4);
assert_eq!(slice, vec![&env, 0, 1, 2, 3]);
let slice = vec.slice(..=3);
assert_eq!(slice, vec![&env, 0, 1, 2, 3]);
let slice = vec.slice(1..4);
assert_eq!(slice, vec![&env, 1, 2, 3]);
let slice = vec.slice(1..=3);
assert_eq!(slice, vec![&env, 1, 2, 3]);
let slice = vec.slice((Bound::Excluded(0), Bound::Included(3)));
assert_eq!(slice, vec![&env, 1, 2, 3]);
let slice = vec.slice((Bound::Excluded(0), Bound::Excluded(3)));
assert_eq!(slice, vec![&env, 1, 2]);
}
#[test]
fn test_vec_iter() {
let env = Env::default();
let vec: Vec<()> = vec![&env];
let mut iter = vec.iter();
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
let vec = vec![&env, 0, 1, 2, 3, 4];
let mut iter = vec.iter();
assert_eq!(iter.len(), 5);
assert_eq!(iter.next(), Some(0));
assert_eq!(iter.len(), 4);
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.len(), 3);
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.len(), 2);
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.len(), 1);
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
let mut iter = vec.iter();
assert_eq!(iter.len(), 5);
assert_eq!(iter.next(), Some(0));
assert_eq!(iter.len(), 4);
assert_eq!(iter.next_back(), Some(4));
assert_eq!(iter.len(), 3);
assert_eq!(iter.next_back(), Some(3));
assert_eq!(iter.len(), 2);
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.len(), 1);
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next_back(), None);
let mut iter = vec.iter().rev();
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next_back(), Some(0));
assert_eq!(iter.next_back(), Some(1));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next_back(), None);
}
#[test]
#[should_panic(expected = "Error(Value, UnexpectedType)")]
fn test_vec_iter_panic_on_conversion() {
let env = Env::default();
let vec: Val = (1i32,).try_into_val(&env).unwrap();
let vec: Vec<i64> = vec.try_into_val(&env).unwrap();
let mut iter = vec.iter();
iter.next();
}
#[test]
fn test_vec_try_iter() {
let env = Env::default();
let vec: Vec<()> = vec![&env];
let mut iter = vec.try_iter();
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
let vec = vec![&env, 0, 1, 2, 3, 4];
let mut iter = vec.try_iter();
assert_eq!(iter.len(), 5);
assert_eq!(iter.next(), Some(Ok(0)));
assert_eq!(iter.len(), 4);
assert_eq!(iter.next(), Some(Ok(1)));
assert_eq!(iter.len(), 3);
assert_eq!(iter.next(), Some(Ok(2)));
assert_eq!(iter.len(), 2);
assert_eq!(iter.next(), Some(Ok(3)));
assert_eq!(iter.len(), 1);
assert_eq!(iter.next(), Some(Ok(4)));
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
let mut iter = vec.try_iter();
assert_eq!(iter.len(), 5);
assert_eq!(iter.next(), Some(Ok(0)));
assert_eq!(iter.len(), 4);
assert_eq!(iter.next_back(), Some(Ok(4)));
assert_eq!(iter.len(), 3);
assert_eq!(iter.next_back(), Some(Ok(3)));
assert_eq!(iter.len(), 2);
assert_eq!(iter.next(), Some(Ok(1)));
assert_eq!(iter.len(), 1);
assert_eq!(iter.next(), Some(Ok(2)));
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next_back(), None);
let mut iter = vec.try_iter().rev();
assert_eq!(iter.next(), Some(Ok(4)));
assert_eq!(iter.next_back(), Some(Ok(0)));
assert_eq!(iter.next_back(), Some(Ok(1)));
assert_eq!(iter.next(), Some(Ok(3)));
assert_eq!(iter.next(), Some(Ok(2)));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next_back(), None);
}
#[test]
fn test_vec_try_iter_error_on_conversion() {
let env = Env::default();
let vec: Val = (1i64, 2i32).try_into_val(&env).unwrap();
let vec: Vec<i64> = vec.try_into_val(&env).unwrap();
let mut iter = vec.try_iter();
assert_eq!(iter.next(), Some(Ok(1)));
assert_eq!(iter.next(), Some(Err(ConversionError.into())));
}
#[test]
fn test_vec_iter_into_vec() {
let env = Env::default();
let vec = vec![&env, 0, 1, 2, 3, 4];
let mut iter = vec.try_iter();
assert_eq!(iter.next(), Some(Ok(0)));
assert_eq!(iter.next(), Some(Ok(1)));
assert_eq!(iter.into_vec(), vec![&env, 2, 3, 4]);
}
#[test]
fn test_contains() {
let env = Env::default();
let vec = vec![&env, 0, 3, 5, 7, 9, 5];
assert_eq!(vec.contains(&2), false);
assert_eq!(vec.contains(2), false);
assert_eq!(vec.contains(&3), true);
assert_eq!(vec.contains(3), true);
assert_eq!(vec.contains(&5), true);
assert_eq!(vec.contains(5), true);
}
#[test]
fn test_first_index_of() {
let env = Env::default();
let vec = vec![&env, 0, 3, 5, 7, 9, 5];
assert_eq!(vec.first_index_of(&2), None);
assert_eq!(vec.first_index_of(2), None);
assert_eq!(vec.first_index_of(&3), Some(1));
assert_eq!(vec.first_index_of(3), Some(1));
assert_eq!(vec.first_index_of(&5), Some(2));
assert_eq!(vec.first_index_of(5), Some(2));
}
#[test]
fn test_last_index_of() {
let env = Env::default();
let vec = vec![&env, 0, 3, 5, 7, 9, 5];
assert_eq!(vec.last_index_of(&2), None);
assert_eq!(vec.last_index_of(2), None);
assert_eq!(vec.last_index_of(&3), Some(1));
assert_eq!(vec.last_index_of(3), Some(1));
assert_eq!(vec.last_index_of(&5), Some(5));
assert_eq!(vec.last_index_of(5), Some(5));
}
#[test]
fn test_binary_search() {
let env = Env::default();
let vec = vec![&env, 0, 3, 5, 5, 7, 9];
assert_eq!(vec.binary_search(&2), Err(1));
assert_eq!(vec.binary_search(2), Err(1));
assert_eq!(vec.binary_search(&3), Ok(1));
assert_eq!(vec.binary_search(3), Ok(1));
assert_eq!(vec.binary_search(&5), Ok(3));
assert_eq!(vec.binary_search(5), Ok(3));
}
#[cfg(not(target_family = "wasm"))]
#[test]
fn test_scval_accessibility_from_udt_types() {
use crate::TryFromVal;
let env = Env::default();
let v = vec![&env, 1];
let val: ScVal = v.clone().try_into().unwrap();
let roundtrip = Vec::<i64>::try_from_val(&env, &val).unwrap();
assert_eq!(v, roundtrip);
}
#[test]
fn test_insert_and_set() {
let env = Env::default();
let mut v = Vec::<i64>::new(&env);
v.insert(0, 3);
v.insert(0, 1);
v.insert(1, 4);
v.insert(3, 6);
assert_eq!(v, vec![&env, 1, 4, 3, 6]);
v.set(0, 7);
v.set(1, 6);
v.set(2, 2);
v.set(3, 5);
assert_eq!(v, vec![&env, 7, 6, 2, 5]);
}
#[test]
fn test_is_empty_and_len() {
let env = Env::default();
let mut v: Vec<i32> = vec![&env, 1, 4, 3];
assert_eq!(v.is_empty(), false);
assert_eq!(v.len(), 3);
v = vec![&env];
assert_eq!(v.is_empty(), true);
assert_eq!(v.len(), 0);
}
#[test]
fn test_push_pop_front() {
let env = Env::default();
let mut v = Vec::<i64>::new(&env);
v.push_front(42);
assert_eq!(v, vec![&env, 42]);
v.push_front(1);
assert_eq!(v, vec![&env, 1, 42]);
v.push_front(5);
assert_eq!(v, vec![&env, 5, 1, 42]);
v.push_front(7);
assert_eq!(v, vec![&env, 7, 5, 1, 42]);
let popped = v.pop_front();
assert_eq!(popped, Some(7));
assert_eq!(v, vec![&env, 5, 1, 42]);
let popped = v.try_pop_front();
assert_eq!(popped, Ok(Some(5)));
assert_eq!(v, vec![&env, 1, 42]);
let popped = v.pop_front_unchecked();
assert_eq!(popped, 1);
assert_eq!(v, vec![&env, 42]);
let popped = v.try_pop_front_unchecked();
assert_eq!(popped, Ok(42));
assert_eq!(v, vec![&env]);
assert_eq!(v.pop_front(), None);
}
#[test]
#[should_panic(expected = "Error(Value, UnexpectedType)")]
fn test_pop_front_panics_on_conversion() {
let env = Env::default();
let v: Val = (1i32,).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
v.pop_front();
}
#[test]
fn test_try_pop_front_errors_on_conversion() {
let env = Env::default();
let v: Val = (1i64, 2i32).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
assert_eq!(v.try_pop_front(), Ok(Some(1)));
assert_eq!(v.try_pop_front(), Err(ConversionError.into()));
}
#[test]
#[should_panic(expected = "Error(Value, UnexpectedType)")]
fn test_pop_front_unchecked_panics_on_conversion() {
let env = Env::default();
let v: Val = (1i32,).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
v.pop_front_unchecked();
}
#[test]
#[should_panic(expected = "HostError: Error(Object, IndexBounds)")]
fn test_pop_front_unchecked_panics_on_out_of_bounds() {
let env = Env::default();
let mut v = Vec::<i64>::new(&env);
v.pop_front_unchecked();
}
#[test]
fn test_try_pop_front_unchecked_errors_on_conversion() {
let env = Env::default();
let v: Val = (1i64, 2i32).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
assert_eq!(v.try_pop_front_unchecked(), Ok(1));
assert_eq!(v.try_pop_front_unchecked(), Err(ConversionError.into()));
}
#[test]
#[should_panic(expected = "HostError: Error(Object, IndexBounds)")]
fn test_try_pop_front_unchecked_panics_on_out_of_bounds() {
let env = Env::default();
let mut v = Vec::<i64>::new(&env);
let _ = v.try_pop_front_unchecked();
}
#[test]
fn test_push_pop_back() {
let env = Env::default();
let mut v = Vec::<i64>::new(&env);
v.push_back(42);
assert_eq!(v, vec![&env, 42]);
v.push_back(1);
assert_eq!(v, vec![&env, 42, 1]);
v.push_back(5);
assert_eq!(v, vec![&env, 42, 1, 5]);
v.push_back(7);
assert_eq!(v, vec![&env, 42, 1, 5, 7]);
let popped = v.pop_back();
assert_eq!(popped, Some(7));
assert_eq!(v, vec![&env, 42, 1, 5]);
let popped = v.try_pop_back();
assert_eq!(popped, Ok(Some(5)));
assert_eq!(v, vec![&env, 42, 1]);
let popped = v.pop_back_unchecked();
assert_eq!(popped, 1);
assert_eq!(v, vec![&env, 42]);
let popped = v.try_pop_back_unchecked();
assert_eq!(popped, Ok(42));
assert_eq!(v, vec![&env]);
assert_eq!(v.pop_back(), None);
}
#[test]
#[should_panic(expected = "Error(Value, UnexpectedType)")]
fn test_pop_back_panics_on_conversion() {
let env = Env::default();
let v: Val = (1i32,).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
v.pop_back();
}
#[test]
fn test_try_pop_back_errors_on_conversion() {
let env = Env::default();
let v: Val = (1i32, 2i64).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
assert_eq!(v.try_pop_back(), Ok(Some(2)));
assert_eq!(v.try_pop_back(), Err(ConversionError.into()));
}
#[test]
#[should_panic(expected = "Error(Value, UnexpectedType)")]
fn test_pop_back_unchecked_panics_on_conversion() {
let env = Env::default();
let v: Val = (1i32,).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
v.pop_back_unchecked();
}
#[test]
#[should_panic(expected = "HostError: Error(Object, IndexBounds)")]
fn test_pop_back_unchecked_panics_on_out_of_bounds() {
let env = Env::default();
let mut v = Vec::<i64>::new(&env);
v.pop_back_unchecked();
}
#[test]
fn test_try_pop_back_unchecked_errors_on_conversion() {
let env = Env::default();
let v: Val = (1i32, 2i64).try_into_val(&env).unwrap();
let mut v: Vec<i64> = v.try_into_val(&env).unwrap();
assert_eq!(v.try_pop_back_unchecked(), Ok(2));
assert_eq!(v.try_pop_back_unchecked(), Err(ConversionError.into()));
}
#[test]
#[should_panic(expected = "HostError: Error(Object, IndexBounds)")]
fn test_try_pop_back_unchecked_panics_on_out_of_bounds() {
let env = Env::default();
let mut v = Vec::<i64>::new(&env);
let _ = v.try_pop_back_unchecked();
}
#[test]
fn test_get() {
let env = Env::default();
let v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
assert_eq!(v.get(3), Some(5));
assert_eq!(v.get(0), Some(0));
assert_eq!(v.get(1), Some(3));
assert_eq!(v.get(2), Some(5));
assert_eq!(v.get(5), Some(9));
assert_eq!(v.get(4), Some(7));
assert_eq!(v.get(v.len()), None);
assert_eq!(v.get(v.len() + 1), None);
assert_eq!(v.get(u32::MAX), None);
let v = Vec::<i64>::new(&env);
assert_eq!(v.get(0), None);
assert_eq!(v.get(v.len()), None);
assert_eq!(v.get(v.len() + 1), None);
assert_eq!(v.get(u32::MAX), None);
}
#[test]
#[should_panic(expected = "Error(Value, UnexpectedType)")]
fn test_get_panics_on_conversion() {
let env = Env::default();
let v: Val = (1i64, 2i32).try_into_val(&env).unwrap();
let v: Vec<i64> = v.try_into_val(&env).unwrap();
assert_eq!(v.get(1), Some(5));
}
#[test]
fn test_try_get() {
let env = Env::default();
let v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
assert_eq!(v.try_get(3), Ok(Some(5)));
assert_eq!(v.try_get(0), Ok(Some(0)));
assert_eq!(v.try_get(1), Ok(Some(3)));
assert_eq!(v.try_get(2), Ok(Some(5)));
assert_eq!(v.try_get(5), Ok(Some(9)));
assert_eq!(v.try_get(4), Ok(Some(7)));
assert_eq!(v.try_get(v.len()), Ok(None));
assert_eq!(v.try_get(v.len() + 1), Ok(None));
assert_eq!(v.try_get(u32::MAX), Ok(None));
let v = Vec::<i64>::new(&env);
assert_eq!(v.try_get(0), Ok(None));
assert_eq!(v.try_get(v.len()), Ok(None));
assert_eq!(v.try_get(v.len() + 1), Ok(None));
assert_eq!(v.try_get(u32::MAX), Ok(None));
let v: Val = (1i64, 2i32).try_into_val(&env).unwrap();
let v: Vec<i64> = v.try_into_val(&env).unwrap();
assert_eq!(v.try_get(0), Ok(Some(1)));
assert_eq!(v.try_get(1), Err(ConversionError.into()));
}
#[test]
fn test_get_unchecked() {
let env = Env::default();
let v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
assert_eq!(v.get_unchecked(3), 5);
assert_eq!(v.get_unchecked(0), 0);
assert_eq!(v.get_unchecked(1), 3);
assert_eq!(v.get_unchecked(2), 5);
assert_eq!(v.get_unchecked(5), 9);
assert_eq!(v.get_unchecked(4), 7);
}
#[test]
#[should_panic(expected = "Error(Value, UnexpectedType)")]
fn test_get_unchecked_panics_on_conversion() {
let env = Env::default();
let v: Val = (1i64, 2i32).try_into_val(&env).unwrap();
let v: Vec<i64> = v.try_into_val(&env).unwrap();
v.get_unchecked(1);
}
#[test]
#[should_panic(expected = "HostError: Error(Object, IndexBounds)")]
fn test_get_unchecked_panics_on_out_of_bounds() {
let env = Env::default();
let v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
_ = v.get_unchecked(v.len()); }
#[test]
fn test_try_get_unchecked() {
let env = Env::default();
let v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
assert_eq!(v.try_get_unchecked(3), Ok(5));
assert_eq!(v.try_get_unchecked(0), Ok(0));
assert_eq!(v.try_get_unchecked(1), Ok(3));
assert_eq!(v.try_get_unchecked(2), Ok(5));
assert_eq!(v.try_get_unchecked(5), Ok(9));
assert_eq!(v.try_get_unchecked(4), Ok(7));
let v: Val = (1i64, 2i32).try_into_val(&env).unwrap();
let v: Vec<i64> = v.try_into_val(&env).unwrap();
assert_eq!(v.try_get_unchecked(0), Ok(1));
assert_eq!(v.try_get_unchecked(1), Err(ConversionError.into()));
}
#[test]
#[should_panic(expected = "HostError: Error(Object, IndexBounds)")]
fn test_try_get_unchecked_panics() {
let env = Env::default();
let v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
_ = v.try_get_unchecked(v.len()); }
#[test]
fn test_remove() {
let env = Env::default();
let mut v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
assert_eq!(v.remove(0), Some(()));
assert_eq!(v.remove(2), Some(()));
assert_eq!(v.remove(3), Some(()));
assert_eq!(v, vec![&env, 3, 5, 7]);
assert_eq!(v.len(), 3);
assert_eq!(v.remove(v.len()), None);
assert_eq!(v.remove(v.len() + 1), None);
assert_eq!(v.remove(u32::MAX), None);
assert_eq!(v.remove(0), Some(()));
assert_eq!(v.remove(0), Some(()));
assert_eq!(v.remove(0), Some(()));
assert_eq!(v, vec![&env]);
assert_eq!(v.len(), 0);
assert_eq!(v.remove(0), None);
assert_eq!(v.remove(v.len()), None);
assert_eq!(v.remove(v.len() + 1), None);
assert_eq!(v.remove(u32::MAX), None);
}
#[test]
fn test_remove_unchecked() {
let env = Env::default();
let mut v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
assert_eq!(v.remove_unchecked(0), ());
assert_eq!(v.remove_unchecked(2), ());
assert_eq!(v.remove_unchecked(3), ());
assert_eq!(v, vec![&env, 3, 5, 7]);
assert_eq!(v.len(), 3);
assert_eq!(v.remove_unchecked(0), ());
assert_eq!(v.remove_unchecked(0), ());
assert_eq!(v.remove_unchecked(0), ());
assert_eq!(v, vec![&env]);
assert_eq!(v.len(), 0);
}
#[test]
#[should_panic(expected = "HostError: Error(Object, IndexBounds)")]
fn test_remove_unchecked_panics() {
let env = Env::default();
let mut v: Vec<i64> = vec![&env, 0, 3, 5, 5, 7, 9];
v.remove_unchecked(v.len())
}
}