From fd1b777ec9bc70e8444c12cb453d14e72db2462c Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 1 Apr 2022 21:56:58 +0200 Subject: yaml::db_insert(): Generalise YAML walking function Split `db_insert()` into one function to do the YAML document recursion and another to do the database insertion. This will allow us to reuse the YAML document recursion function for database `UPDATE` queries. --- src/yaml.rs | 59 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/yaml.rs b/src/yaml.rs index cc9d9a3..acf1a9e 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -36,25 +36,12 @@ pub fn db_insert( table_name: &str, table_columns: &HashSet, ) -> Result<(), crate::Error> { - match doc { - yaml::Yaml::Array(ref mut array) => { - for yaml_value in array { - db_insert(yaml_value, tx, table_name, table_columns)?; - } - } - yaml::Yaml::Hash(ref mut hash) => { + with_hash( + doc, + &mut |hash| { use std::borrow::Cow; - let keys: Vec = hash.keys().map(|k| k.clone()).collect(); - let columns_as_yaml: Vec = table_columns.iter() - .map(|c| yaml::Yaml::from_str(c)) - .collect(); - - for key in keys.iter() { - if !columns_as_yaml.contains(key) { - hash.remove(key); - } - } + hash_filter_table_columns(hash, &table_columns); let mut stmt = tx.prepare( &format!( @@ -81,9 +68,47 @@ pub fn db_insert( let values = hash.values().map(|v| Yaml(Cow::Borrowed(v))); stmt.insert(rusqlite::params_from_iter(values))?; + + Ok(()) + } + ) +} + +/// Parse a YAML document and run a function for all hashes in the document. +fn with_hash( + doc: &mut yaml::Yaml, + run: &mut F, +) -> Result<(), crate::Error> +where F: FnMut(&mut yaml::Hash) -> Result<(), crate::Error> +{ + match doc { + yaml::Yaml::Array(ref mut array) => { + for yaml_value in array { + with_hash(yaml_value, run)?; + } + } + yaml::Yaml::Hash(ref mut hash) => { + run(hash)?; } _ => {} } Ok(()) } + +/// Remove keys in `table_columns` from `hash`. +fn hash_filter_table_columns( + hash: &mut yaml::Hash, + table_columns: &HashSet, +) { + let keys: Vec = hash.keys().map(|k| k.clone()).collect(); + let columns_as_yaml: Vec = table_columns.iter() + .map(|c| yaml::Yaml::from_str(c)) + .collect(); + + for key in keys.iter() { + if !columns_as_yaml.contains(key) { + hash.remove(key); + } + } +} -- cgit v1.2.3