Selaa lähdekoodia

Removed janky serde-based deserialization in favour of Modelable::build_from().

Kestrel 2 vuotta sitten
vanhempi
commit
cd004859e2

+ 14 - 0
microrm-macros/src/lib.rs

@@ -78,6 +78,10 @@ pub fn derive_entity(tokens: TokenStream) -> TokenStream {
     let mut foreign_keys = Vec::new();
     let mut foreign_key_impls = Vec::new();
 
+    let mut build_clauses = Vec::new();
+
+    let mut index : usize = 0;
+
     for name in fields.named.iter() {
         let converted_case =
             format!("{}", name.ident.as_ref().unwrap().clone()).to_case(Case::UpperCamel);
@@ -117,6 +121,9 @@ pub fn derive_entity(tokens: TokenStream) -> TokenStream {
         }
 
         value_references.push(quote! { &self. #field_name });
+
+        index += 1;
+        build_clauses.push(quote! { #field_name: <#ty as #microrm_ref::model::Modelable>::build_from(stmt, #index)?.0 });
     }
 
     let column_types_name = format_ident!("{}_COLUMN_TYPES", struct_name.to_string().to_case(Case::ScreamingSnake));
@@ -203,6 +210,13 @@ pub fn derive_entity(tokens: TokenStream) -> TokenStream {
             fn values(&self) -> Vec<&dyn #microrm_ref::model::Modelable> {
                 vec![ #(#value_references),* ]
             }
+
+            fn build_from(stmt: &#microrm_ref::re_export::sqlite::Statement) -> #microrm_ref::re_export::sqlite::Result<Self> {
+                Ok(Self {
+                    #(#build_clauses),*
+                })
+            }
+
             fn column_types() -> &'static [&'static str] {
                 #column_types_name.as_ref()
             }

+ 1 - 1
microrm/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "microrm"
-version = "0.2.3"
+version = "0.2.4"
 edition = "2021"
 license = "BSD-4-Clause"
 authors = ["Kestrel <kestrel@flying-kestrel.ca>"]

+ 4 - 1
microrm/src/model.rs

@@ -1,5 +1,4 @@
 mod create;
-pub(crate) mod load;
 pub(crate) mod store;
 
 // Modelable implementations
@@ -79,6 +78,10 @@ pub trait Entity: 'static + for<'de> serde::Deserialize<'de> + serde::Serialize
         Self: Sized;
     fn values(&self) -> Vec<&dyn Modelable>;
 
+    fn build_from(stmt: &sqlite::Statement) -> sqlite::Result<Self>
+    where
+        Self: Sized;
+
     fn foreign_keys() -> &'static [&'static dyn EntityForeignKey<Self::Column>];
 }
 

+ 0 - 151
microrm/src/model/load.rs

@@ -1,151 +0,0 @@
-use super::Modelable;
-use serde::de::{Visitor, IntoDeserializer};
-
-pub struct RowDeserializer<'de, 'l> {
-    row: &'de sqlite::Statement<'l>,
-    col_index: usize,
-}
-
-impl<'de, 'l> RowDeserializer<'de, 'l> {
-    pub fn from_row(row: &'de sqlite::Statement<'l>) -> Self {
-        // we skip the rowid by starting at index 1
-        Self { row, col_index: 1 }
-    }
-}
-
-impl<'de, 'a, 'l> serde::de::Deserializer<'de> for &'a mut RowDeserializer<'de, 'l> {
-    type Error = super::ModelError;
-
-    fn deserialize_any<V: Visitor<'de>>(self, _v: V) -> Result<V::Value, Self::Error> {
-        todo!()
-    }
-
-    fn deserialize_bool<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_bool(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_i8<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_i8(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_i16<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_i16(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_i32<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_i32(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_i64<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_i64(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_u8<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_u8(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_u16<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_u16(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_u32<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_u32(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_u64<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_u64(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_string(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_byte_buf<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-        let res = v.visit_byte_buf(built.0);
-        self.col_index += built.1;
-        res
-    }
-
-    fn deserialize_enum<V: Visitor<'de>>(self, _name: &'static str, _variants: &'static [&'static str], v: V) -> Result<V::Value, Self::Error> {
-        let built : (String, _) = Modelable::build_from(self.row, self.col_index)
-            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
-
-        v.visit_enum(built.0.into_deserializer())
-    }
-
-    fn deserialize_struct<V: Visitor<'de>>(
-        self,
-        _name: &'static str,
-        _fields: &'static [&'static str],
-        v: V,
-    ) -> Result<V::Value, Self::Error> {
-        v.visit_seq(self)
-    }
-
-    fn deserialize_newtype_struct<V: Visitor<'de>>(
-        self,
-        _name: &'static str,
-        v: V,
-    ) -> Result<V::Value, Self::Error> {
-        v.visit_seq(self)
-    }
-
-    serde::forward_to_deserialize_any! {
-        i128 u128 f32 f64 char str
-        bytes option unit unit_struct seq tuple
-        tuple_struct map identifier ignored_any
-    }
-}
-
-impl<'de, 'l> serde::de::SeqAccess<'de> for RowDeserializer<'de, 'l> {
-    type Error = super::ModelError;
-
-    fn next_element_seed<T: serde::de::DeserializeSeed<'de>>(
-        &mut self,
-        seed: T,
-    ) -> Result<Option<T::Value>, Self::Error> {
-        seed.deserialize(self).map(Some)
-    }
-}

+ 0 - 4
microrm/src/model/store.rs

@@ -9,7 +9,3 @@ pub fn serialize_into<T: Entity>(stmt: &mut sqlite::Statement, value: &T) -> sql
 
     Ok(())
 }
-
-/*pub fn serialize_as_row<T: Entity>(value: &T) -> Vec<&dyn rusqlite::ToSql> {
-    value.values()
-}*/

+ 4 - 8
microrm/src/query.rs

@@ -188,8 +188,7 @@ impl<'l> QueryInterface<'l> {
 
                 self.expect_one_result(stmt, &mut |stmt| {
                     let id: i64 = stmt.read(0).ok()?;
-                    let mut rd = crate::model::load::RowDeserializer::from_row(stmt);
-                    Some(WithID::wrap(T::deserialize(&mut rd).ok()?, id))
+                    Some(WithID::wrap(T::build_from(stmt).ok()?, id))
                 })
             },
         )
@@ -233,8 +232,7 @@ impl<'l> QueryInterface<'l> {
 
                 self.expect_one_result(stmt, &mut |stmt| {
                     let id: i64 = stmt.read(0).ok()?;
-                    let mut rd = crate::model::load::RowDeserializer::from_row(stmt);
-                    Some(WithID::wrap(T::deserialize(&mut rd).ok()?, id))
+                    Some(WithID::wrap(T::build_from(stmt).ok()?, id))
                 })
             },
         )
@@ -364,8 +362,7 @@ impl<'l> QueryInterface<'l> {
 
                 self.expect_one_result(stmt, &mut |stmt| {
                     let id: i64 = stmt.read(0).ok()?;
-                    let mut rd = crate::model::load::RowDeserializer::from_row(stmt);
-                    Some(WithID::wrap(T::deserialize(&mut rd).ok()?, id))
+                    Some(WithID::wrap(T::build_from(stmt).ok()?, id))
                 })
             },
         )
@@ -408,8 +405,7 @@ impl<'l> QueryInterface<'l> {
                     }
 
                     let id: i64 = stmt.read(0).ok()?;
-                    let mut rd = crate::model::load::RowDeserializer::from_row(stmt);
-                    res.push(WithID::wrap(T::deserialize(&mut rd).ok()?, id));
+                    res.push(WithID::wrap(T::build_from(stmt).ok()?, id));
                 }
 
                 Some(res)