diff options
Diffstat (limited to 'tvix/eval/src/value/list.rs')
-rw-r--r-- | tvix/eval/src/value/list.rs | 108 |
1 files changed, 55 insertions, 53 deletions
diff --git a/tvix/eval/src/value/list.rs b/tvix/eval/src/value/list.rs index 81abb3c07e..2b8b3de28d 100644 --- a/tvix/eval/src/value/list.rs +++ b/tvix/eval/src/value/list.rs @@ -1,21 +1,25 @@ //! This module implements Nix lists. -use std::fmt::Display; +use std::ops::Index; +use std::rc::Rc; -use crate::errors::ErrorKind; -use crate::vm::VM; +use imbl::{vector, Vector}; +use serde::Deserialize; + +use super::thunk::ThunkSet; +use super::TotalDisplay; use super::Value; #[repr(transparent)] -#[derive(Clone, Debug, PartialEq)] -pub struct NixList(Vec<Value>); +#[derive(Clone, Debug, Deserialize)] +pub struct NixList(Rc<Vector<Value>>); -impl Display for NixList { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl TotalDisplay for NixList { + fn total_fmt(&self, f: &mut std::fmt::Formatter<'_>, set: &mut ThunkSet) -> std::fmt::Result { f.write_str("[ ")?; - for v in &self.0 { - v.fmt(f)?; + for v in self { + v.total_fmt(f, set)?; f.write_str(" ")?; } @@ -23,39 +27,13 @@ impl Display for NixList { } } -impl From<Vec<Value>> for NixList { - fn from(vs: Vec<Value>) -> Self { - Self(vs) - } -} - -#[cfg(feature = "arbitrary")] -mod arbitrary { - use proptest::{ - prelude::{any_with, Arbitrary}, - strategy::{BoxedStrategy, Strategy}, - }; - - use super::*; - - impl Arbitrary for NixList { - type Parameters = <Vec<Value> as Arbitrary>::Parameters; - type Strategy = BoxedStrategy<Self>; - - fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { - any_with::<Vec<Value>>(args).prop_map(Self).boxed() - } +impl From<Vector<Value>> for NixList { + fn from(vs: Vector<Value>) -> Self { + Self(Rc::new(vs)) } } impl NixList { - pub fn concat(&self, other: &Self) -> Self { - let mut lhs = self.clone(); - let mut rhs = other.clone(); - lhs.0.append(&mut rhs.0); - lhs - } - pub fn len(&self) -> usize { self.0.len() } @@ -64,6 +42,10 @@ impl NixList { self.0.get(i) } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + pub fn construct(count: usize, stack_slice: Vec<Value>) -> Self { debug_assert!( count == stack_slice.len(), @@ -72,29 +54,49 @@ impl NixList { stack_slice.len(), ); - NixList(stack_slice) + NixList(Rc::new(Vector::from_iter(stack_slice))) } - pub fn iter(&self) -> std::slice::Iter<Value> { + pub fn iter(&self) -> vector::Iter<Value> { self.0.iter() } - pub fn into_iter(self) -> std::vec::IntoIter<Value> { - self.0.into_iter() + pub fn ptr_eq(&self, other: &Self) -> bool { + Rc::ptr_eq(&self.0, &other.0) } - /// Compare `self` against `other` for equality using Nix equality semantics - pub fn nix_eq(&self, other: &Self, vm: &mut VM) -> Result<bool, ErrorKind> { - if self.len() != other.len() { - return Ok(false); - } + pub fn into_inner(self) -> Vector<Value> { + Rc::try_unwrap(self.0).unwrap_or_else(|rc| (*rc).clone()) + } - for (v1, v2) in self.iter().zip(other.iter()) { - if !v1.nix_eq(v2, vm)? { - return Ok(false); - } - } + #[deprecated(note = "callers should avoid constructing from Vec")] + pub fn from_vec(vs: Vec<Value>) -> Self { + Self(Rc::new(Vector::from_iter(vs))) + } +} + +impl IntoIterator for NixList { + type Item = Value; + type IntoIter = imbl::vector::ConsumingIter<Value>; + + fn into_iter(self) -> Self::IntoIter { + self.into_inner().into_iter() + } +} + +impl<'a> IntoIterator for &'a NixList { + type Item = &'a Value; + type IntoIter = imbl::vector::Iter<'a, Value>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + +impl Index<usize> for NixList { + type Output = Value; - Ok(true) + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] } } |