use std::collections::{BTreeMap, BTreeSet}; use std::marker::PhantomData; use std::str::FromStr; use chrono::{DateTime, Utc}; use imbl::OrdMap; pub use imbl_value::Value; use patch_db::value::InternedString; pub use patch_db::{HasModel, MutateResult, PatchDb}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use crate::prelude::*; pub fn to_value(value: &T) -> Result where T: Serialize, { patch_db::value::to_value(value).with_kind(ErrorKind::Serialization) } pub fn from_value(value: Value) -> Result where T: DeserializeOwned, { patch_db::value::from_value(value).with_kind(ErrorKind::Deserialization) } pub type TypedPatchDb = patch_db::TypedPatchDb; /// &mut Model <=> &mut Value #[repr(transparent)] #[derive(Debug)] pub struct Model { value: Value, phantom: PhantomData, } impl Model { pub fn de(&self) -> Result { from_value(self.value.clone()) } } impl Model { pub fn new(value: &T) -> Result { Ok(Self::from(to_value(value)?)) } pub fn ser(&mut self, value: &T) -> Result<(), Error> { self.value = to_value(value)?; Ok(()) } } impl Serialize for Model { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { self.value.serialize(serializer) } } impl<'de, T: Serialize + Deserialize<'de>> Deserialize<'de> for Model { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { use serde::de::Error; Self::new(&T::deserialize(deserializer)?).map_err(D::Error::custom) } } impl Model { pub fn replace(&mut self, value: &T) -> Result { let orig = self.de()?; self.ser(value)?; Ok(orig) } pub fn mutate(&mut self, f: impl FnOnce(&mut T) -> Result) -> Result { let mut orig = self.de()?; let res = f(&mut orig)?; self.ser(&orig)?; Ok(res) } pub fn map_mutate(&mut self, f: impl FnOnce(T) -> Result) -> Result { let orig = self.de()?; let res = f(orig)?; self.ser(&res)?; Ok(res) } } impl Clone for Model { fn clone(&self) -> Self { Self { value: self.value.clone(), phantom: PhantomData, } } } impl From for Model { fn from(value: Value) -> Self { Self { value, phantom: PhantomData, } } } impl From> for Value { fn from(value: Model) -> Self { value.value } } impl<'a, T> From<&'a Value> for &'a Model { fn from(value: &'a Value) -> Self { unsafe { std::mem::transmute(value) } } } impl<'a, T> From<&'a Model> for &'a Value { fn from(value: &'a Model) -> Self { unsafe { std::mem::transmute(value) } } } impl<'a, T> From<&'a mut Value> for &mut Model { fn from(value: &'a mut Value) -> Self { unsafe { std::mem::transmute(value) } } } impl<'a, T> From<&'a mut Model> for &mut Value { fn from(value: &'a mut Model) -> Self { unsafe { std::mem::transmute(value) } } } impl patch_db::Model for Model { type Model = Model; } impl Model> { pub fn transpose(self) -> Option> { use patch_db::ModelExt; if self.value.is_null() { None } else { Some(self.transmute(|a| a)) } } pub fn transpose_ref(&self) -> Option<&Model> { use patch_db::ModelExt; if self.value.is_null() { None } else { Some(self.transmute_ref(|a| a)) } } pub fn transpose_mut(&mut self) -> Option<&mut Model> { use patch_db::ModelExt; if self.value.is_null() { None } else { Some(self.transmute_mut(|a| a)) } } pub fn from_option(opt: Option>) -> Self { use patch_db::ModelExt; match opt { Some(a) => a.transmute(|a| a), None => Self::from_value(Value::Null), } } } pub trait Map: DeserializeOwned + Serialize { type Key; type Value; fn key_str(key: &Self::Key) -> Result, Error>; fn key_string(key: &Self::Key) -> Result { Ok(InternedString::intern(Self::key_str(key)?.as_ref())) } } impl Map for BTreeMap where A: serde::Serialize + serde::de::DeserializeOwned + Ord + AsRef, B: serde::Serialize + serde::de::DeserializeOwned, { type Key = A; type Value = B; fn key_str(key: &Self::Key) -> Result, Error> { Ok(key.as_ref()) } } impl Map for BTreeMap, B> where A: serde::Serialize + serde::de::DeserializeOwned + Ord, B: serde::Serialize + serde::de::DeserializeOwned, { type Key = JsonKey; type Value = B; fn key_str(key: &Self::Key) -> Result, Error> { serde_json::to_string(key).with_kind(ErrorKind::Serialization) } } impl Map for OrdMap where A: serde::Serialize + serde::de::DeserializeOwned + Clone + Ord + AsRef, B: serde::Serialize + serde::de::DeserializeOwned + Clone, { type Key = A; type Value = B; fn key_str(key: &Self::Key) -> Result, Error> { Ok(key.as_ref()) } } impl Model where T::Value: Serialize, { pub fn insert_model( &mut self, key: &T::Key, value: Model, ) -> Result>, Error> { use patch_db::ModelExt; use serde::ser::Error; let v = value.into_value(); match &mut self.value { Value::Object(o) => { let prev = o.insert(T::key_string(key)?, v); Ok(prev.map(|v| Model::from_value(v))) } v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Serialization, } .into()), } } pub fn insert( &mut self, key: &T::Key, value: &T::Value, ) -> Result>, Error> { self.insert_model(key, Model::new(value)?) } pub fn upsert(&mut self, key: &T::Key, value: F) -> Result<&mut Model, Error> where F: FnOnce() -> Result, { use serde::ser::Error; match &mut self.value { Value::Object(o) => { use patch_db::ModelExt; let s = T::key_str(key)?; let exists = o.contains_key(s.as_ref()); let res = self.transmute_mut(|v| { use patch_db::value::index::Index; s.as_ref().index_or_insert(v) }); if !exists { res.ser(&value()?)?; } Ok(res) } v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Serialization, } .into()), } } } impl Model where T::Key: FromStr + Ord + Clone, Error: From<::Err>, { pub fn keys(&self) -> Result, Error> { use serde::de::Error; match &self.value { Value::Object(o) => o .keys() .cloned() .map(|k| Ok(T::Key::from_str(&*k)?)) .collect(), v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Deserialization, } .into()), } } pub fn into_entries(self) -> Result)>, Error> { use patch_db::ModelExt; use serde::de::Error; match self.value { Value::Object(o) => o .into_iter() .map(|(k, v)| Ok((T::Key::from_str(&*k)?, Model::from_value(v)))) .collect(), v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Deserialization, } .into()), } } pub fn as_entries(&self) -> Result)>, Error> { use patch_db::ModelExt; use serde::de::Error; match &self.value { Value::Object(o) => o .iter() .map(|(k, v)| Ok((T::Key::from_str(&**k)?, Model::value_as(v)))) .collect(), v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Deserialization, } .into()), } } pub fn as_entries_mut(&mut self) -> Result)>, Error> { use patch_db::ModelExt; use serde::de::Error; match &mut self.value { Value::Object(o) => o .iter_mut() .map(|(k, v)| Ok((T::Key::from_str(&**k)?, Model::value_as_mut(v)))) .collect(), v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Deserialization, } .into()), } } } impl Model { pub fn contains_key(&self, key: &T::Key) -> Result { use serde::de::Error; let s = T::key_str(key)?; match &self.value { Value::Object(o) => Ok(o.contains_key(s.as_ref())), v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Deserialization, } .into()), } } pub fn into_idx(self, key: &T::Key) -> Option> { use patch_db::ModelExt; let s = T::key_str(key).ok()?; match &self.value { Value::Object(o) if o.contains_key(s.as_ref()) => Some(self.transmute(|v| { use patch_db::value::index::Index; s.as_ref().index_into_owned(v).unwrap() })), _ => None, } } pub fn as_idx<'a>(&'a self, key: &T::Key) -> Option<&'a Model> { use patch_db::ModelExt; let s = T::key_str(key).ok()?; match &self.value { Value::Object(o) if o.contains_key(s.as_ref()) => Some(self.transmute_ref(|v| { use patch_db::value::index::Index; s.as_ref().index_into(v).unwrap() })), _ => None, } } pub fn as_idx_mut<'a>(&'a mut self, key: &T::Key) -> Option<&'a mut Model> { use patch_db::ModelExt; let s = T::key_str(key).ok()?; match &mut self.value { Value::Object(o) if o.contains_key(s.as_ref()) => Some(self.transmute_mut(|v| { use patch_db::value::index::Index; s.as_ref().index_or_insert(v) })), _ => None, } } pub fn remove(&mut self, key: &T::Key) -> Result>, Error> { use serde::ser::Error; match &mut self.value { Value::Object(o) => { let v = o.remove(T::key_str(key)?.as_ref()); Ok(v.map(patch_db::ModelExt::from_value)) } v => Err(patch_db::value::Error { source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), kind: patch_db::value::ErrorKind::Serialization, } .into()), } } } #[repr(transparent)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct JsonKey(pub T); impl From for JsonKey { fn from(value: T) -> Self { Self::new(value) } } impl JsonKey { pub fn new(value: T) -> Self { Self(value) } pub fn unwrap(self) -> T { self.0 } pub fn new_ref(value: &T) -> &Self { unsafe { std::mem::transmute(value) } } pub fn new_mut(value: &mut T) -> &mut Self { unsafe { std::mem::transmute(value) } } } impl std::ops::Deref for JsonKey { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } impl std::ops::DerefMut for JsonKey { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl FromStr for JsonKey { type Err = Error; fn from_str(s: &str) -> Result { serde_json::from_str(s).with_kind(ErrorKind::Deserialization) } } impl Serialize for JsonKey { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { use serde::ser::Error; serde_json::to_string(&self.0) .map_err(S::Error::custom)? .serialize(serializer) } } // { "foo": "bar" } -> "{ \"foo\": \"bar\" }" impl<'de, T: DeserializeOwned> Deserialize<'de> for JsonKey { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { use serde::de::Error; let string = String::deserialize(deserializer)?; Ok(Self( serde_json::from_str(&string).map_err(D::Error::custom)?, )) } } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct WithTimeData { pub created_at: DateTime, pub updated_at: DateTime, pub value: T, } impl WithTimeData { pub fn new(value: T) -> Self { let now = Utc::now(); Self { created_at: now, updated_at: now, value, } } } impl std::ops::Deref for WithTimeData { type Target = T; fn deref(&self) -> &Self::Target { &self.value } } impl std::ops::DerefMut for WithTimeData { fn deref_mut(&mut self) -> &mut Self::Target { self.updated_at = Utc::now(); &mut self.value } }