diff options
Diffstat (limited to 'tvix/eval')
-rw-r--r-- | tvix/eval/src/value/attrs.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs index d8e3001f4a18..6e839798d4ac 100644 --- a/tvix/eval/src/value/attrs.rs +++ b/tvix/eval/src/value/attrs.rs @@ -246,6 +246,26 @@ impl NixAttrs { }) } + pub fn into_iter(self) -> IntoIter { + match self.0 { + AttrsRep::Empty => IntoIter(IntoIterRepr::Empty), + AttrsRep::KV { name, value } => IntoIter(IntoIterRepr::Finite( + vec![ + (NixString::NAME_REF.clone(), name), + (NixString::VALUE_REF.clone(), value), + ] + .into_iter(), + )), + AttrsRep::Map(map) => IntoIter(IntoIterRepr::Map(map.into_iter())), + } + } + + /// Same as into_iter(), but marks call sites which rely on the + /// iteration being lexicographic. + pub fn into_iter_sorted(self) -> IntoIter { + self.into_iter() + } + /// Construct an iterator over all the keys of the attribute set pub fn keys(&self) -> Keys { Keys(match &self.0 { @@ -541,3 +561,35 @@ impl<'a> IntoIterator for &'a NixAttrs { self.iter() } } + +/// Internal representation of an owning attrset iterator +pub enum IntoIterRepr { + Empty, + Finite(std::vec::IntoIter<(NixString, Value)>), + Map(std::collections::btree_map::IntoIter<NixString, Value>), +} + +#[repr(transparent)] +pub struct IntoIter(IntoIterRepr); + +impl Iterator for IntoIter { + type Item = (NixString, Value); + + fn next(&mut self) -> Option<Self::Item> { + match &mut self.0 { + IntoIterRepr::Empty => None, + IntoIterRepr::Map(inner) => inner.next(), + IntoIterRepr::Finite(inner) => inner.next(), + } + } +} + +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + match &self.0 { + IntoIterRepr::Empty => 0, + IntoIterRepr::Map(inner) => inner.len(), + IntoIterRepr::Finite(inner) => inner.len(), + } + } +} |