From 9fd80fae5868b28c92e22a0389cc91b505985ce8 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 22 Mar 2021 15:49:51 -0600 Subject: [PATCH] give up on ORM style models --- patch-db/src/lib.rs | 303 ++++++++----------------------------------- patch-db/src/test.rs | 10 +- 2 files changed, 57 insertions(+), 256 deletions(-) diff --git a/patch-db/src/lib.rs b/patch-db/src/lib.rs index a09dced..cf20aa7 100644 --- a/patch-db/src/lib.rs +++ b/patch-db/src/lib.rs @@ -1,7 +1,8 @@ use std::collections::HashMap; use std::fs::OpenOptions; -use std::future::Future; use std::io::Error as IOError; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; use std::path::Path; use std::sync::Arc; @@ -956,276 +957,82 @@ impl Default for Locker { } } -pub trait ModelData: Send + Sync { - type Inner; - fn apply< - 'a, - F: FnOnce(&mut Self::Inner) -> ResFut + Send + Sync + 'a, - ResFut: Future + Send + Sync + 'a, - Res: Send + Sync + 'a, - >( - &'a mut self, - f: F, - ) -> BoxFuture<'a, Res>; -} - -pub enum Never {} -impl ModelData for Never { - type Inner = Never; - fn apply< - 'a, - F: FnOnce(&mut Self::Inner) -> ResFut + 'a, - ResFut: Future + 'a, - Res: 'a, - >( - &'a mut self, - _: F, - ) -> BoxFuture<'a, Res> { - match *self {} +pub struct ModelData Deserialize<'de>>(T); +impl Deserialize<'de>> Deref for ModelData { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 } } -pub enum GenericModelData Deserialize<'de>, Parent: ModelData> { - Uninitialized(Vec>), - Ref( - Arc &mut T + Send + Sync>, - Arc>, - ), - Owned(Box), -} -impl Deserialize<'de>, Parent: ModelData> GenericModelData { - pub fn is_initialized(&self) -> bool { - match self { - GenericModelData::Uninitialized(_) => false, - _ => true, - } - } - async fn apply< - F: FnOnce(&mut T) -> ResFut + Send + Sync, - ResFut: Future + Send + Sync, - Res: Send + Sync, - >( - &mut self, - f: F, - ) -> Res { - match self { - GenericModelData::Owned(data) => f(data).await, - GenericModelData::Ref(g, parent) => parent.lock().await.apply(|t| f(g(t))).await, - _ => panic!("uninitialized"), - } - } -} -impl Deserialize<'de> + Send + Sync, Parent: ModelData> ModelData - for GenericModelData -{ - type Inner = T; - fn apply< - 'a, - F: FnOnce(&mut Self::Inner) -> ResFut + Send + Sync + 'a, - ResFut: Future + Send + Sync + 'a, - Res: Send + Sync + 'a, - >( - &'a mut self, - f: F, - ) -> BoxFuture<'a, Res> { - self.apply(f).boxed() - } -} - -pub struct ChildHooks { - init_parent: Box FnOnce(&'a mut T) -> BoxFuture<'a, ()> + Send + Sync>, - save_data: Box< - dyn Fn() -> BoxFuture<'static, Result, serde_json::Error>> - + Send - + Sync, - >, -} -impl ChildHooks { - async fn init_parent(self, parent: &mut T) { - (self.init_parent)(parent).await - } - async fn save_data(&self) -> Result, serde_json::Error> { - (self.save_data)().await - } -} - -pub trait Model { - type Data: ModelData; -} - -impl Model for Never { - type Data = Never; -} - -pub struct GenericModel Deserialize<'de>, Parent: ModelData> { - data: Arc>>, +pub struct ModelDataMut Deserialize<'de>> { + original: Value, + current: T, ptr: JsonPointer, } -impl GenericModel +impl Deserialize<'de>> ModelDataMut { + pub async fn save(self, tx: &mut Tx) -> Result<(), Error> { + let current = serde_json::to_value(&self.current)?; + let mut diff = DiffPatch(json_patch::diff(&self.original, ¤t)); + let target = tx.get_value(&self.ptr, None).await?; + diff.rebase(&DiffPatch(json_patch::diff(&self.original, &target))); + diff.0.prepend(&self.ptr); + tx.apply(diff); + Ok(()) + } +} +impl Deserialize<'de>> Deref for ModelDataMut { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.current + } +} +impl Deserialize<'de>> DerefMut for ModelDataMut { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.current + } +} + +pub struct Model Deserialize<'de>> { + ptr: JsonPointer, + phantom: PhantomData, +} +impl Model where T: Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static, - Parent: ModelData + 'static, { pub fn new(ptr: JsonPointer) -> Self { Self { - data: Arc::new(Mutex::new(GenericModelData::Uninitialized(Vec::new()))), ptr, + phantom: PhantomData, } } - // locks - async fn fetch(&mut self, tx: &mut Tx) -> Result<(), Error> { - let mut data = self.data.lock().await; - if let GenericModelData::Uninitialized(children) = &mut *data { - let mut a: Box = tx.get(&self.ptr, LockType::None).await?; - for child in std::mem::replace(children, Vec::new()) { - child.init_parent(&mut a).await; - } - *data = GenericModelData::Owned(a); - } - - Ok(()) - } - pub async fn lock(&self, tx: &mut Tx, lock: LockType) { tx.lock(&self.ptr, lock).await } - // locks - pub async fn peek< - Tx: Checkpoint, - F: FnOnce(&T) -> ResFut + Send + Sync, - ResFut: Future + Send + Sync, - Res: Send + Sync, - >( - &mut self, - tx: &mut Tx, - f: F, - ) -> Result { - self.lock(tx, LockType::Read).await; - self.fetch(tx).await?; - Ok(self.data.lock().await.apply(|t| f(t)).await) + pub async fn get(&self, tx: &mut Tx) -> Result, Error> { + Ok(ModelData(tx.get(&self.ptr, LockType::Read).await?)) } - // locks - pub async fn apply< - Tx: Checkpoint, - F: FnOnce(&mut T) -> ResFut + Send + Sync, - ResFut: Future + Send + Sync, - Res: Send + Sync, - >( - &mut self, - tx: &mut Tx, - f: F, - ) -> Result { + pub async fn get_mut(&mut self, tx: &mut Tx) -> Result, Error> { self.lock(tx, LockType::Write).await; - self.fetch(tx).await?; - Ok(self.data.lock().await.apply(f).await) + let original = tx.get_value(&self.ptr, None).await?; + let current = serde_json::from_value(original.clone())?; + Ok(ModelDataMut { + original, + current, + ptr: self.ptr.clone(), + }) } - // locks - pub async fn child( - &mut self, - path: &JsonPointer, - f: F, - ) -> GenericModel> - where - C: Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static, - F: Fn(&mut T) -> &mut C + Send + Sync + 'static, - S: AsRef, - V: SegList, - for<'v> &'v V: IntoIterator, - { - let arc_f = Arc::new(f); - let ptr = self.ptr.clone() + path; - let mut data_ref = self.data.lock().await; - let data = if let GenericModelData::Uninitialized(children) = &mut *data_ref { - let data = Arc::new(Mutex::new(GenericModelData::Uninitialized(Vec::new()))); - let init_parent_data = data.clone(); - let parent_data = self.data.clone(); - let save_data_data = data.clone(); - let save_data_ptr = ptr.clone(); - children.push(ChildHooks { - init_parent: Box::new(move |parent| { - async move { - let mut data_ref = init_parent_data.lock().await; - let self_data = std::mem::replace( - &mut *data_ref, - GenericModelData::Uninitialized(Vec::new()), - ); - match self_data { - GenericModelData::Owned(t) => *arc_f(parent) = *t, - GenericModelData::Uninitialized(children) => { - for child in children { - child.init_parent(arc_f(parent)).await; // TODO: can probably parallelize - } - } - _ => (), - } - *data_ref = GenericModelData::Ref(arc_f, parent_data); - } - .boxed() - }), - save_data: Box::new(move || { - let ptr = save_data_ptr.clone(); - let data = save_data_data.clone(); - async move { - let mut data_ref = data.lock().await; - if let GenericModelData::Uninitialized(children) = &mut *data_ref { - let mut res = Vec::new(); - for child in children { - res.append(&mut child.save_data().await?) - } - Ok(res) - } else { - Ok(vec![( - ptr, - data_ref - .apply(|t| futures::future::ready(serde_json::to_value(t))) - .await?, - )]) - } - } - .boxed() - }), - }); - data - } else { - Arc::new(Mutex::new(GenericModelData::Ref( - arc_f.clone(), - self.data.clone(), - ))) - }; - GenericModel { data, ptr } - } - - /// locks - pub async fn save(&mut self, tx: &mut Tx) -> Result<(), Error> { - let mut data_ref = self.data.lock().await; - for (ptr, value) in if let GenericModelData::Uninitialized(children) = &mut *data_ref { - let mut res = Vec::new(); - for child in children { - res.append(&mut child.save_data().await?) - } - res - } else { - vec![( - self.ptr.clone(), - data_ref - .apply(|t| futures::future::ready(serde_json::to_value(t))) - .await?, - )] - } { - tx.put_value(&ptr, &value).await?; + pub fn child Deserialize<'de>>(&self, index: &str) -> Model { + let mut ptr = self.ptr.clone(); + ptr.push_end(index); + Model { + ptr, + phantom: PhantomData, } - Ok(()) } } - -impl Model for GenericModel -where - T: Serialize + for<'de> Deserialize<'de> + Send + Sync, - Parent: ModelData, -{ - type Data = GenericModelData; -} diff --git a/patch-db/src/test.rs b/patch-db/src/test.rs index 84fbc76..e702e72 100644 --- a/patch-db/src/test.rs +++ b/patch-db/src/test.rs @@ -15,10 +15,7 @@ pub struct Sample { b: Child, } -pub struct SampleModel(GenericModel); -impl Model for SampleModel { - type Data = GenericModelData; -} +pub struct SampleModel(Model); #[derive(Debug, serde::Deserialize, serde::Serialize)] pub struct Child { @@ -26,7 +23,4 @@ pub struct Child { b: usize, } -pub struct ChildModel(GenericModel); -impl Model for ChildModel { - type Data = GenericModelData; -} +pub struct ChildModel(Model);