From f8a8eca83664a4d79971b535be09d18968c2eaf0 Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Wed, 7 Feb 2024 22:43:12 +0000 Subject: [PATCH] Record cleanup (#11726) # Description Does a little cleanup in `record.rs`: - Makes the `record!` macro more hygienic. - Converts regular comments to doc comments from #11718. - Converts the `Record` iterators to new types. --- crates/nu-protocol/src/value/mod.rs | 3 +- crates/nu-protocol/src/value/record.rs | 117 ++++++++++++++++++++----- 2 files changed, 97 insertions(+), 23 deletions(-) diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 6bb74cd2bc..6be79edd18 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -4,10 +4,11 @@ mod from_value; mod lazy_record; mod path; mod range; -mod record; mod stream; mod unit; +pub mod record; + use crate::ast::{Bits, Boolean, CellPath, Comparison, PathMember}; use crate::ast::{Math, Operator}; use crate::engine::{Closure, EngineState}; diff --git a/crates/nu-protocol/src/value/record.rs b/crates/nu-protocol/src/value/record.rs index cbdef4e547..97565c4f5e 100644 --- a/crates/nu-protocol/src/value/record.rs +++ b/crates/nu-protocol/src/value/record.rs @@ -26,25 +26,25 @@ impl Record { } } - // Constructor that checks that `cols` and `vals` are of the same length. - // - // WARNING! Panics with assertion failure if cols and vals have different length! - // Should be used only when the same lengths are guaranteed! - // - // For perf reasons does not validate the rest of the record assumptions. - // - unique keys + /// Constructor that checks that `cols` and `vals` are of the same length. + /// + /// WARNING! Panics with assertion failure if cols and vals have different length! + /// Should be used only when the same lengths are guaranteed! + /// + /// For perf reasons does not validate the rest of the record assumptions. + /// - unique keys pub fn from_raw_cols_vals_unchecked(cols: Vec, vals: Vec) -> Self { assert_eq!(cols.len(), vals.len()); Self { cols, vals } } - // Constructor that checks that `cols` and `vals` are of the same length. - // - // Returns None if cols and vals have different length. - // - // For perf reasons does not validate the rest of the record assumptions. - // - unique keys + /// Constructor that checks that `cols` and `vals` are of the same length. + /// + /// Returns None if cols and vals have different length. + /// + /// For perf reasons does not validate the rest of the record assumptions. + /// - unique keys pub fn from_raw_cols_vals( cols: Vec, vals: Vec, @@ -314,6 +314,7 @@ impl Record { impl FromIterator<(String, Value)> for Record { fn from_iter>(iter: T) -> Self { let (cols, vals) = iter.into_iter().unzip(); + // TODO: should this check for duplicate keys/columns? Self { cols, vals } } } @@ -328,7 +329,29 @@ impl Extend<(String, Value)> for Record { } } -pub type IntoIter = std::iter::Zip, std::vec::IntoIter>; +pub struct IntoIter { + iter: std::iter::Zip, std::vec::IntoIter>, +} + +impl Iterator for IntoIter { + type Item = (String, Value); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.iter.len() + } +} impl IntoIterator for Record { type Item = (String, Value); @@ -336,11 +359,35 @@ impl IntoIterator for Record { type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { - self.cols.into_iter().zip(self.vals) + IntoIter { + iter: self.cols.into_iter().zip(self.vals), + } } } -pub type Iter<'a> = std::iter::Zip, std::slice::Iter<'a, Value>>; +pub struct Iter<'a> { + iter: std::iter::Zip, std::slice::Iter<'a, Value>>, +} + +impl<'a> Iterator for Iter<'a> { + type Item = (&'a String, &'a Value); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +impl<'a> DoubleEndedIterator for Iter<'a> { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +impl<'a> ExactSizeIterator for Iter<'a> { + fn len(&self) -> usize { + self.iter.len() + } +} impl<'a> IntoIterator for &'a Record { type Item = (&'a String, &'a Value); @@ -348,11 +395,35 @@ impl<'a> IntoIterator for &'a Record { type IntoIter = Iter<'a>; fn into_iter(self) -> Self::IntoIter { - self.cols.iter().zip(&self.vals) + Iter { + iter: self.cols.iter().zip(&self.vals), + } } } -pub type IterMut<'a> = std::iter::Zip, std::slice::IterMut<'a, Value>>; +pub struct IterMut<'a> { + iter: std::iter::Zip, std::slice::IterMut<'a, Value>>, +} + +impl<'a> Iterator for IterMut<'a> { + type Item = (&'a String, &'a mut Value); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +impl<'a> DoubleEndedIterator for IterMut<'a> { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} + +impl<'a> ExactSizeIterator for IterMut<'a> { + fn len(&self) -> usize { + self.iter.len() + } +} impl<'a> IntoIterator for &'a mut Record { type Item = (&'a String, &'a mut Value); @@ -360,7 +431,9 @@ impl<'a> IntoIterator for &'a mut Record { type IntoIter = IterMut<'a>; fn into_iter(self) -> Self::IntoIter { - self.cols.iter().zip(&mut self.vals) + IterMut { + iter: self.cols.iter().zip(&mut self.vals), + } } } @@ -480,9 +553,9 @@ impl ExactSizeIterator for Drain<'_> { #[macro_export] macro_rules! record { {$($col:expr => $val:expr),+ $(,)?} => { - $crate::Record::from_raw_cols_vals_unchecked ( - vec![$($col.into(),)+], - vec![$($val,)+] + $crate::Record::from_raw_cols_vals_unchecked( + ::std::vec![$($col.into(),)+], + ::std::vec![$($val,)+] ) }; {} => {