From 4fb636186049a6ece09997da6306888156209cbb Mon Sep 17 00:00:00 2001 From: glendc Date: Mon, 8 Apr 2024 13:37:35 +0200 Subject: [PATCH] support append/from_iter with Into more flexibility without a cost if not desired --- venndb-macros/src/generate_db.rs | 18 ++++++++- venndb-usage/src/main.rs | 69 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/venndb-macros/src/generate_db.rs b/venndb-macros/src/generate_db.rs index 424bdb8..77e23aa 100644 --- a/venndb-macros/src/generate_db.rs +++ b/venndb-macros/src/generate_db.rs @@ -250,6 +250,11 @@ fn generate_db_struct_method_from_rows( name ); + let method_iter_doc = format!( + "Construct a new database from the given iterator of items that can be turned into [`{}`] instances.", + name + ); + let return_type = db_error.generate_fn_output(name_db, quote! { ::std::vec::Vec<#name> }, quote! { Self }); let append_internal_call = db_error.generate_fn_error_kind_usage( @@ -273,6 +278,16 @@ fn generate_db_struct_method_from_rows( db.rows = rows; #fn_result } + + #[doc=#method_iter_doc] + #vis fn from_iter(iter: I) -> #return_type + where + I: ::std::iter::IntoIterator, + Item: ::std::convert::Into<#name>, + { + let rows: ::std::vec::Vec<#name> = iter.into_iter().map(::std::convert::Into::into).collect(); + Self::from_rows(rows) + } } } @@ -367,8 +382,9 @@ fn generate_db_struct_method_append( quote! { #[doc=#method_doc] - #vis fn append(&mut self, data: #name) -> #append_return_type { + #vis fn append(&mut self, data: impl ::std::convert::Into<#name>) -> #append_return_type { let index = self.rows.len(); + let data = data.into(); #append_internal_call self.rows.push(data); #append_return_output diff --git a/venndb-usage/src/main.rs b/venndb-usage/src/main.rs index 4617106..5a05c1f 100644 --- a/venndb-usage/src/main.rs +++ b/venndb-usage/src/main.rs @@ -15,6 +15,25 @@ pub struct Employee { department: Department, } +#[derive(Debug)] +pub struct L1Engineer { + id: u32, + name: String, +} + +impl From for Employee { + fn from(engineer: L1Engineer) -> Employee { + Employee { + id: engineer.id, + name: engineer.name, + is_manager: false, + is_admin: false, + is_active: true, + department: Department::Engineering, + } + } +} + #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum Department { Engineering, @@ -77,6 +96,25 @@ mod tests { assert_eq!(employee.name, "Alice"); } + #[test] + fn test_append_into() { + let mut db = EmployeeDB::default(); + db.append(L1Engineer { + id: 1, + name: "Alice".to_string(), + }) + .unwrap(); + assert_eq!(db.len(), 1); + + let employee: &Employee = db.get_by_id(&1).unwrap(); + assert_eq!(employee.id, 1); + assert_eq!(employee.name, "Alice"); + assert!(!employee.is_manager); + assert!(!employee.is_admin); + assert!(employee.is_active); + assert_eq!(employee.department, Department::Engineering); + } + #[test] fn test_employee_query_filters() { let mut db = EmployeeDB::default(); @@ -240,6 +278,37 @@ mod tests { assert_eq!(rows[1].id, 2); } + #[test] + fn test_from_iter() { + let db = EmployeeDB::from_iter([ + L1Engineer { + id: 1, + name: "Alice".to_string(), + }, + L1Engineer { + id: 2, + name: "Bob".to_string(), + }, + ]) + .unwrap(); + + assert_eq!(db.len(), 2); + assert_eq!(db.capacity(), 2); + + let mut query = db.query(); + query.is_manager(true); + assert!(query.execute().is_none()); + + query + .reset() + .is_manager(false) + .department(Department::Engineering); + let results: Vec<_> = query.execute().unwrap().iter().collect(); + assert_eq!(results.len(), 2); + assert_eq!(results[0].id, 1); + assert_eq!(results[1].id, 2); + } + #[test] fn test_query_reset() { let mut db = EmployeeDB::default();