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.
This commit is contained in:
Ian Manske 2024-02-07 22:43:12 +00:00 committed by GitHub
parent 20aa59085b
commit f8a8eca836
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 97 additions and 23 deletions

View File

@ -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};

View File

@ -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<String>, vals: Vec<Value>) -> 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<String>,
vals: Vec<Value>,
@ -314,6 +314,7 @@ impl Record {
impl FromIterator<(String, Value)> for Record {
fn from_iter<T: IntoIterator<Item = (String, Value)>>(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<String>, std::vec::IntoIter<Value>>;
pub struct IntoIter {
iter: std::iter::Zip<std::vec::IntoIter<String>, std::vec::IntoIter<Value>>,
}
impl Iterator for IntoIter {
type Item = (String, Value);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl DoubleEndedIterator for IntoIter {
fn next_back(&mut self) -> Option<Self::Item> {
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, String>, std::slice::Iter<'a, Value>>;
pub struct Iter<'a> {
iter: std::iter::Zip<std::slice::Iter<'a, String>, std::slice::Iter<'a, Value>>,
}
impl<'a> Iterator for Iter<'a> {
type Item = (&'a String, &'a Value);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<'a> DoubleEndedIterator for Iter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
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::Iter<'a, String>, std::slice::IterMut<'a, Value>>;
pub struct IterMut<'a> {
iter: std::iter::Zip<std::slice::Iter<'a, String>, std::slice::IterMut<'a, Value>>,
}
impl<'a> Iterator for IterMut<'a> {
type Item = (&'a String, &'a mut Value);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<'a> DoubleEndedIterator for IterMut<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
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),
}
}
}
@ -481,8 +554,8 @@ impl ExactSizeIterator for Drain<'_> {
macro_rules! record {
{$($col:expr => $val:expr),+ $(,)?} => {
$crate::Record::from_raw_cols_vals_unchecked(
vec![$($col.into(),)+],
vec![$($val,)+]
::std::vec![$($col.into(),)+],
::std::vec![$($val,)+]
)
};
{} => {