From a95958de6b1897a5b9a39672f66f93283b207511 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 8 Sep 2022 15:39:13 -0600 Subject: [PATCH] wip --- patch-db/src/projector.rs | 119 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 patch-db/src/projector.rs diff --git a/patch-db/src/projector.rs b/patch-db/src/projector.rs new file mode 100644 index 0000000..93ad86f --- /dev/null +++ b/patch-db/src/projector.rs @@ -0,0 +1,119 @@ +use std::collections::BTreeMap; + +use json_patch::Patch; +use json_ptr::JsonPointer; +use serde_json::Value; + +use crate::patch::diff; +use crate::DiffPatch; + +fn project_patch_default( + p: &mut P, + persistent: &Value, + volatile: &Value, + projection: &mut Value, + persistent_patch: &DiffPatch, + volatile_patch: &DiffPatch, +) -> Patch { + let new_persistent = { + let mut d = persistent.clone(); + json_patch::patch(&mut d, &*persistent_patch).unwrap(); + d + }; + let new_volatile = { + let mut d = volatile.clone(); + json_patch::patch(&mut d, &*volatile_patch).unwrap(); + d + }; + let new = p.project(&new_persistent, &volatile); + let res = diff(projection, &new).0; + *projection = new; + res +} + +pub trait DataProjector { + fn project(&mut self, data: &Value, volatile: &Value) -> Value; + /// Only implement to improve performance! + /// it MUST produce the same results as the default implementation. + /// You can test this using the `test_project_patch` function defined in this module + fn project_patch( + &mut self, + data: &Value, + volatile: &Value, + projection: &mut Value, + data_patch: &DiffPatch, + volatile_patch: &DiffPatch, + ) -> Patch { + project_patch_default(self, data, volatile, projection, patch) + } +} + +pub fn test_project_patch( + p: &mut P, + data: &Value, + volatile: &Value, + patch: &DiffPatch, +) { + let projected = p.project(data, volatile); + let (default_projected, _default_patch) = { + let mut d = projected.clone(); + let patch = project_patch_default(p, data, volatile, &mut d, patch); + (d, patch) + }; + let (opt_projected, opt_patch) = { + let mut d = projected.clone(); + let patch = p.project_patch(data, volatile, &mut d, patch); + (d, patch) + }; + assert_eq!(default_projected, opt_projected); + let opt_projected_patched = { + let mut d = projected.clone(); + json_patch::patch(&mut d, &opt_patch).unwrap(); + d + }; + assert_eq!(default_projected, opt_projected_patched); +} + +pub struct NoProjection; +impl DataProjector for NoProjection { + fn project(&mut self, data: &Value, volatile: &Value) -> Value { + let mut res = serde_json::Map::with_capacity(2); + res.insert("data".to_string(), data.clone()); + res.insert("volatile".to_string(), volatile.clone()); + } + fn project_patch( + &mut self, + _data: &Value, + _projection: &mut Value, + _patch: &DiffPatch, + ) -> Patch { + Patch(Vec::new()) + } +} + +pub enum SimpleReactive { + Object(BTreeMap), + Expr { + relevant_fields: Box bool + Send + Sync + 'static>, + computation: Box Result + Send + Sync + 'static>, + }, +} +impl DataProjector for SimpleReactive { + fn project(&mut self, data: &Value) -> Value { + match self { + SimpleReactive::Object(o) => { + let mut res = serde_json::Map::with_capacity(o.len()); + for (idx, value) in o { + res.insert(idx.clone(), value.project(data)); + } + Value::Object(res) + } + SimpleReactive::Expr { + relevant_fields, + computation, + } => { + unimplemented!() + } + } + } +}