From 45d116dc84a8d941c37d96a2a88c8e540a4f0f8d Mon Sep 17 00:00:00 2001 From: dcz Date: Thu, 15 Jun 2023 16:34:03 +0000 Subject: [PATCH] Add into_iter for NamedRows With this change, the user of NamedRows no longer needs to care about the .next field. --- cozo-core/src/runtime/db.rs | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/cozo-core/src/runtime/db.rs b/cozo-core/src/runtime/db.rs index ea796ba5..ad941d79 100644 --- a/cozo-core/src/runtime/db.rs +++ b/cozo-core/src/runtime/db.rs @@ -125,6 +125,27 @@ pub(crate) struct BadDbInit(#[help] pub(crate) String); #[diagnostic(code(tx::import_into_index))] pub(crate) struct ImportIntoIndex(pub(crate) String); +/// Iterates over all rows in sequence +pub struct RowsIter { + rows: NamedRows, +} + +impl Iterator for RowsIter { + type Item = Tuple; + fn next(&mut self) -> Option { + if self.rows.rows.is_empty() { + if let Some(rows) = self.rows.next.take() { + self.rows = *rows; + self.next() + } else { + None + } + } else { + Some(self.rows.rows.remove(0)) + } + } +} + #[derive(serde_derive::Serialize, serde_derive::Deserialize, Debug, Clone, Default)] /// Rows in a relation, together with headers for the fields. pub struct NamedRows { @@ -167,6 +188,11 @@ impl NamedRows { collected } + /// Convert into an iterator over rows. + pub fn into_iter(self) -> RowsIter { + RowsIter { rows: self } + } + /// Convert to a JSON object pub fn into_json(self) -> JsonValue { let nxt = match self.next { @@ -1935,3 +1961,46 @@ pub(crate) fn seconds_since_the_epoch() -> Result { #[cfg(target_arch = "wasm32")] Ok(js_sys::Date::now()) } + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn empty() { + assert_eq!( + RowsIter { + rows: NamedRows::default() + } + .next(), + None, + ); + } + #[test] + fn few() { + let mut rows = RowsIter { + rows: NamedRows { + rows: vec![Vec::new()], + ..Default::default() + }, + }; + assert_eq!(rows.next(), Some(Vec::new()),); + assert_eq!(rows.next(), None,); + } + + #[test] + fn many() { + let mut rows = RowsIter { + rows: NamedRows { + rows: vec![Vec::new()], + next: Some(Box::new(NamedRows { + rows: vec![Vec::new()], + ..Default::default() + })), + ..Default::default() + }, + }; + assert_eq!(rows.next(), Some(Vec::new()),); + assert_eq!(rows.next(), Some(Vec::new()),); + assert_eq!(rows.next(), None,); + } +}