Browse Source

Replaced Entity::values() uses with visit_values() to remove heap allocations.

Kestrel 2 years ago
parent
commit
edd171a480
4 changed files with 17 additions and 21 deletions
  1. 4 5
      microrm-macros/src/entity.rs
  2. 1 3
      microrm/src/entity.rs
  3. 5 5
      microrm/src/model/store.rs
  4. 7 8
      microrm/src/query/update.rs

+ 4 - 5
microrm-macros/src/entity.rs

@@ -243,11 +243,10 @@ pub(crate) fn derive(tokens: TokenStream) -> TokenStream {
                 // +1 for ID column
                 #field_count + 1
             }
-            fn values(&self) -> Vec<&dyn #microrm_ref::model::Modelable> {
-                vec![ #(#value_references),* ]
-            }
-            fn visit_values<F: FnMut(&dyn #microrm_ref::model::Modelable) -> ()>(&self, visit: &mut F) {
-                #(visit(#value_references));*
+            fn visit_values<E, F: FnMut(&dyn #microrm_ref::model::Modelable) -> (Result<(), E>)>(&self, visit: &mut F) -> Result<(),E> {
+                #(visit(#value_references)?);*;
+
+                Ok(())
             }
 
             fn build_from(stmt: &#microrm_ref::re_export::sqlite::Statement) -> #microrm_ref::re_export::sqlite::Result<Self> {

+ 1 - 3
microrm/src/entity.rs

@@ -11,9 +11,7 @@ pub trait Entity: 'static + for<'de> serde::Deserialize<'de> + serde::Serialize
     fn columns() -> &'static [&'static dyn EntityColumn<Entity = Self>];
     fn id_column() -> Self::IDColumn;
 
-    fn values(&self) -> Vec<&dyn Modelable>;
-    // visit_values() avoids heap allocation at the cost of programming complexity
-    fn visit_values<F: FnMut(&dyn Modelable) -> ()>(&self, visit: &mut F);
+    fn visit_values<E,F: FnMut(&dyn Modelable) -> Result<(),E>>(&self, visit: &mut F) -> Result<(),E>;
 
     fn build_from(stmt: &sqlite::Statement) -> sqlite::Result<Self>
     where

+ 5 - 5
microrm/src/model/store.rs

@@ -2,10 +2,10 @@ use crate::entity::Entity;
 
 pub fn serialize_into<T: Entity>(stmt: &mut sqlite::Statement, value: &T) -> sqlite::Result<()> {
     let mut i = 1;
-    for c in &value.values() {
-        c.bind_to(stmt, i)?;
-        i += 1;
-    }
 
-    Ok(())
+    value.visit_values::<sqlite::Error,_>(&mut |val| {
+        val.bind_to(stmt, i)?;
+        i += 1;
+        Ok(())
+    })
 }

+ 7 - 8
microrm/src/query/update.rs

@@ -94,16 +94,15 @@ impl<'r, 'q, T: Entity> QueryComponent for Entire<'r, 'q, T> {
     }
 
     fn bind(&self, stmt: &mut sqlite::Statement<'_>) -> Result<usize, Error> {
-        let ind = self.wrap.bind(stmt)?;
+        let mut ind = self.wrap.bind(stmt)?;
 
-        let values = self.to.values();
+        self.to.visit_values::<Error,_>(&mut |val| {
+            val.bind_to(stmt, ind)?;
+            ind += 1;
+            Ok(())
+        })?;
 
-        // skip ID
-        for col in 0..T::column_count()-1 {
-            values[col].bind_to(stmt, ind + col)?;
-        }
-
-        Ok(ind + T::column_count() - 1)
+        Ok(ind)
     }
 }