Browse Source

Add JsonWrapper implementation and bump version.

Kestrel 2 years ago
parent
commit
dcd0585a8b
3 changed files with 61 additions and 1 deletions
  1. 1 1
      microrm/Cargo.toml
  2. 3 0
      microrm/src/model.rs
  3. 57 0
      microrm/src/model/json.rs

+ 1 - 1
microrm/Cargo.toml

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

+ 3 - 0
microrm/src/model.rs

@@ -2,6 +2,9 @@ pub(crate) mod store;
 
 // Modelable implementations
 mod modelable;
+mod json;
+
+pub use json::JsonWrapper;
 
 /// A database value, aka a single column of a single row
 pub trait Modelable {

+ 57 - 0
microrm/src/model/json.rs

@@ -0,0 +1,57 @@
+/// Wrapper struct to store a serializable object as JSON transparently in a text column
+pub struct JsonWrapper<T: serde::Serialize + serde::de::DeserializeOwned + 'static> {
+    wrap: T
+}
+
+impl<T: serde::Serialize + serde::de::DeserializeOwned + 'static> JsonWrapper<T> {
+    pub fn wrap(wrap: T) -> Self {
+        Self { wrap }
+    }
+
+    pub fn unwrap(self) -> T {
+        self.wrap
+    }
+}
+
+impl<T: serde::Serialize + serde::de::DeserializeOwned + 'static> AsRef<T> for JsonWrapper<T> {
+    fn as_ref(&self) -> &T {
+        &self.wrap
+    }
+}
+
+impl<T: serde::Serialize + serde::de::DeserializeOwned + 'static> AsMut<T> for JsonWrapper<T> {
+    fn as_mut(&mut self) -> &mut T {
+        &mut self.wrap
+    }
+}
+
+impl<T: serde::Serialize + serde::de::DeserializeOwned + 'static> From<T> for JsonWrapper<T> {
+    fn from(wrap: T) -> Self {
+        Self { wrap }
+    }
+}
+
+impl<T: serde::Serialize + serde::de::DeserializeOwned + 'static> super::Modelable for JsonWrapper<T> {
+    fn bind_to(&self, stmt: &mut sqlite::Statement, col: usize) -> sqlite::Result<()> {
+        serde_json::to_string(&self.wrap).unwrap().bind_to(stmt, col)
+    }
+    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)>
+    where
+        Self: Sized,
+    {
+        let s = String::build_from(stmt, col_offset)?;
+        Ok((
+            Self::wrap(serde_json::from_str::<T>(s.0.as_str()).map_err(|e| sqlite::Error {
+                code: None,
+                message: Some(e.to_string()),
+            })?),
+            1,
+        ))
+    }
+    fn column_type() -> &'static str
+    where
+        Self: Sized,
+    {
+        "text"
+    }
+}