From 079588d5dad43c20073483565e0cde8a512bdb07 Mon Sep 17 00:00:00 2001 From: Jonah Seguin Date: Sat, 21 Jan 2023 19:36:34 -0700 Subject: [PATCH] initial Ref impl (#10) --- musty-proc-macro/src/model/meta_model.rs | 2 +- musty/examples/filter.rs | 2 +- musty/src/filter/value.rs | 20 +++++- musty/src/lib.rs | 1 + musty/src/model.rs | 2 +- musty/src/reference.rs | 91 ++++++++++++++++++++++++ 6 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 musty/src/reference.rs diff --git a/musty-proc-macro/src/model/meta_model.rs b/musty-proc-macro/src/model/meta_model.rs index 6517880..5d9bc5a 100644 --- a/musty-proc-macro/src/model/meta_model.rs +++ b/musty-proc-macro/src/model/meta_model.rs @@ -135,7 +135,7 @@ impl MetaModelDerive { #( #attrs )* - #[derive(Debug, serde::Serialize, serde::Deserialize)] + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #vis struct #ident { #id_attr #id_vis id: musty::prelude::Id<#ident, #id_type>, diff --git a/musty/examples/filter.rs b/musty/examples/filter.rs index fccf882..2a1b895 100644 --- a/musty/examples/filter.rs +++ b/musty/examples/filter.rs @@ -11,7 +11,7 @@ struct User { address: Address, } -#[derive(Debug, Filter, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Filter)] struct Address { country: String, labels: Vec, diff --git a/musty/src/filter/value.rs b/musty/src/filter/value.rs index 13f78a3..990c4a6 100644 --- a/musty/src/filter/value.rs +++ b/musty/src/filter/value.rs @@ -1,4 +1,4 @@ -use crate::{prelude::{Filter, ModelFilter, IdGuard, Id}, Model}; +use crate::{prelude::{Filter, ModelFilter, IdGuard, Id}, Model, reference::Ref}; #[derive(Debug, Clone)] pub enum FilterValue { @@ -77,4 +77,22 @@ impl From> for FilterValue { fn from(id: Id) -> Self { Self::Id(id.inner.map(|i| i.to_string())) } +} + +impl From<&Id> for FilterValue { + fn from(id: &Id) -> Self { + Self::Id(id.inner.as_ref().map(|i| i.to_string())) + } +} + +impl From> for FilterValue { + fn from(r: Ref) -> Self { + r.take_id().into() + } +} + +impl From<&Ref> for FilterValue { + fn from(r: &Ref) -> Self { + r.id().into() + } } \ No newline at end of file diff --git a/musty/src/lib.rs b/musty/src/lib.rs index 13c5922..df32f7c 100644 --- a/musty/src/lib.rs +++ b/musty/src/lib.rs @@ -9,6 +9,7 @@ mod error; mod id; mod model; pub mod filter; +mod reference; #[cfg(feature = "bson")] pub use bson; diff --git a/musty/src/model.rs b/musty/src/model.rs index 1c8de93..72da3aa 100644 --- a/musty/src/model.rs +++ b/musty/src/model.rs @@ -18,7 +18,7 @@ use async_trait::async_trait; #[async_trait] pub trait Model where - Self: Sized + Send + Sync + Serialize + DeserializeOwned + Unpin, + Self: Sized + Send + Sync + Serialize + DeserializeOwned + Unpin + Clone, { type Id: IdGuard; diff --git a/musty/src/reference.rs b/musty/src/reference.rs new file mode 100644 index 0000000..8b30969 --- /dev/null +++ b/musty/src/reference.rs @@ -0,0 +1,91 @@ +use serde::{Serialize, Deserialize}; + +use crate::{Model, id::Id, prelude::Backend, Result, context::Context}; + +#[derive(Clone)] +pub enum Ref { + Id(Id::Id>), + Model(M), +} + +impl Ref { + pub async fn get(&self, db: &crate::Musty) -> Result> + where + M: Context<::Id, B> + 'static, + I: Into::Id>> + Send + Sync, + B: Backend, + { + match self { + Self::Id(id) => Ok(db.inner.get_model_by_id(id.into()).await?), + Self::Model(model) => Ok(Some(model.clone())), + } + } + + pub async fn take(self, db: &crate::Musty) -> Result> + where + M: Context<::Id, B> + 'static, + I: Into::Id>> + Send + Sync, + B: Backend, + { + match self { + Self::Id(id) => Ok(db.inner.get_model_by_id(&id.into()).await?), + Self::Model(model) => Ok(Some(model)), + } + } + + pub fn id(&self) -> &Id::Id> { + match self { + Self::Id(id) => id, + Self::Model(model) => model.id(), + } + } + + pub fn take_id(self) -> Id::Id> { + match self { + Self::Id(id) => id, + Self::Model(model) => model.id().clone(), + } + } +} + +impl From::Id>> for Ref { + fn from(id: Id::Id>) -> Self { + Ref::Id(id) + } +} + +impl From> for Id::Id> { + fn from(id: Ref) -> Self { + match id { + Ref::Id(id) => id, + Ref::Model(model) => model.id().clone(), + } + } +} + +impl<'a, M: Model> From<&'a Ref> for &'a Id::Id> { + fn from(id: &'a Ref) -> Self { + match id { + Ref::Id(id) => id, + Ref::Model(model) => model.id(), + } + } +} + +impl Serialize for Ref { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serde::Serializer, + { + self.id().serialize(serializer) + } +} + +impl<'de, M: Model> Deserialize<'de> for Ref { + fn deserialize(deserializer: D) -> core::result::Result + where + D: serde::Deserializer<'de>, + { + Ok(Ref::Id(Id::deserialize(deserializer)?)) + } +} \ No newline at end of file