diff --git a/patch-db-macro-internals/src/lib.rs b/patch-db-macro-internals/src/lib.rs index 776d1dd..727f97b 100644 --- a/patch-db-macro-internals/src/lib.rs +++ b/patch-db-macro-internals/src/lib.rs @@ -34,8 +34,8 @@ pub fn build_model(item: &DeriveInput) -> TokenStream { Data::Enum(enum_ast) => build_model_enum(item, enum_ast, model_name), _ => panic!("Models can only be created for Structs and Enums"), }; - if item.attrs.iter().any(|a| a.path.is_ident("macro_debug")) { - panic!("{}", res) + if let Some(dbg) = item.attrs.iter().find(|a| a.path.is_ident("macro_debug")) { + return Error::new_spanned(dbg, format!("{}", res)).to_compile_error(); } else { res } @@ -167,8 +167,14 @@ fn separate_option(ty: &Type) -> (bool, &Type) { (false, ty) } -fn impl_fns(children: &[ChildInfo]) -> TokenStream { - let mut res = TokenStream::new(); +struct Fns { + impl_fns: TokenStream, + impl_mut_fns: TokenStream, +} + +fn impl_fns(children: &[ChildInfo]) -> Fns { + let mut impl_fns = TokenStream::new(); + let mut impl_mut_fns = TokenStream::new(); for ChildInfo { vis, name, @@ -206,14 +212,24 @@ fn impl_fns(children: &[ChildInfo]) -> TokenStream { a => a.clone(), }; let (optional, ty) = separate_option(ty); - let model_ty = if *has_model { - quote_spanned! { name.span() => - <#ty as patch_db::HasModel<'a>>::Model - } + let (model_ty, model_mut_ty) = if *has_model { + ( + quote_spanned! { name.span() => + <#ty as patch_db::HasModel>::Model + }, + quote_spanned! { name.span() => + <<#ty as patch_db::HasModel>::Model as patch_db::Model>::Mut<'a> + }, + ) } else { - quote_spanned! { name.span() => - patch_db::GenericModel::<'a, #ty> - } + ( + quote_spanned! { name.span() => + patch_db::GenericModel::<#ty> + }, + quote_spanned! { name.span() => + patch_db::GenericModelMut::<'a, #ty> + }, + ) }; let accessor = if let Some(accessor) = accessor { quote! { [#accessor] } @@ -221,20 +237,33 @@ fn impl_fns(children: &[ChildInfo]) -> TokenStream { quote! {} }; if optional { - res.extend(quote_spanned! { name.span() => - #vis fn #name (&mut self) -> patch_db::OptionModel<'a, #model_ty> { - as patch_db::Model<'a>>::new(&mut self #accessor) + impl_fns.extend(quote_spanned! { name.span() => + #vis fn #name (&self) -> patch_db::OptionModel<#model_ty> { + as patch_db::Model>::new((&**self) #accessor .clone()) + } + }); + impl_mut_fns.extend(quote_spanned! { name.span() => + #vis fn #name (&self) -> patch_db::OptionModelMut<'a, #model_mut_ty> { + as patch_db::ModelMut<'a>>::new(&mut (&mut **self) #accessor) } }); } else { - res.extend(quote_spanned! { name.span() => - #vis fn #name (&mut self) -> #model_ty { - <#model_ty as patch_db::Model<'a>>::new(&mut self #accessor) + impl_fns.extend(quote_spanned! { name.span() => + #vis fn #name (&self) -> #model_ty { + <#model_ty as patch_db::Model>::new((&**self) #accessor .clone()) + } + }); + impl_mut_fns.extend(quote_spanned! { name.span() => + #vis fn #name (&mut self) -> #model_mut_ty { + <#model_mut_ty as patch_db::ModelMut<'a>>::new(&mut (&mut **self) #accessor) } }); } } - res + Fns { + impl_fns, + impl_mut_fns, + } } fn build_model_struct( @@ -261,17 +290,47 @@ fn build_model_struct( let children = ChildInfo::from_fields(&serde_rename_all, &ast.fields); let name = &base.ident; let vis = &base.vis; - let impl_fns = impl_fns(&children); + let Fns { + impl_fns, + impl_mut_fns, + } = impl_fns(&children); quote! { - impl<'a> patch_db::HasModel<'a> for #name { - type Model = #module_name::Model<'a>; + impl patch_db::HasModel for #name { + type Model = #module_name::Model; } #vis mod #module_name { use super::*; #[derive(Debug)] - pub struct Model<'a>(&'a mut patch_db::Value); - impl<'a> patch_db::Model<'a> for Model<'a> { + pub struct Model(patch_db::Value); + impl patch_db::Model for Model { + type T = #name; + type Mut<'a> = ModelMut<'a>; + fn new(value: patch_db::Value) -> Self { + Self(value) + } + fn into_inner(self) -> patch_db::Value { + self.0 + } + } + impl ::core::ops::Deref for Model { + type Target = patch_db::Value; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl ::core::ops::DerefMut for Model { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + impl Model { + #impl_fns + } + + #[derive(Debug)] + pub struct ModelMut<'a>(&'a mut patch_db::Value); + impl<'a> patch_db::ModelMut<'a> for ModelMut<'a> { type T = #name; fn new(value: &'a mut patch_db::Value) -> Self { Self(value) @@ -280,19 +339,19 @@ fn build_model_struct( self.0 } } - impl<'a> ::core::ops::Deref for Model<'a> { + impl<'a> ::core::ops::Deref for ModelMut<'a> { type Target = patch_db::Value; fn deref(&self) -> &Self::Target { &*self.0 } } - impl<'a> ::core::ops::DerefMut for Model<'a> { + impl<'a> ::core::ops::DerefMut for ModelMut<'a> { fn deref_mut(&mut self) -> &mut Self::Target { self.0 } } - impl<'a> Model<'a> { - #impl_fns + impl<'a> ModelMut<'a> { + #impl_mut_fns } } } @@ -348,11 +407,15 @@ fn build_model_enum(base: &DeriveInput, ast: &DataEnum, module_name: Option - Some(#variant_accessor) => Model::#variant_name(#variant_model(&mut value[#content])), + Some(#variant_accessor) => Model::#variant_name(#variant_model(value[#content].clone())), + }); + tag_variants_mut.extend(quote_spanned! { variant_name.span() => + Some(#variant_accessor) => ModelMut::#variant_name(#variant_model_mut(&mut value[#content])), }); } - quote! { - match value[#tag].as_str() { - #tag_variants - _ => Model::Error(value), - } - } + ( + quote! { + match value[#tag].as_str() { + #tag_variants + _ => Model::Error(value), + } + }, + quote! { + match value[#tag].as_str() { + #tag_variants_mut + _ => ModelMut::Error(value), + } + }, + ) } else { let mut tag_variants = TokenStream::new(); + let mut tag_variants_mut = TokenStream::new(); for variant in &ast.variants { let variant_name = &variant.ident; let variant_model = Ident::new(&format!("{}Model", variant_name), variant_name.span()); + let variant_model_mut = + Ident::new(&format!("{}ModelMut", variant_name), variant_name.span()); let variant_accessor = get_accessor(&serde_rename_all, &variant.attrs, variant_name); tag_variants.extend(quote_spanned! { variant_name.span() => Some(#variant_accessor) => Model::#variant_name(#variant_model(value)), }); + tag_variants_mut.extend(quote_spanned! { variant_name.span() => + Some(#variant_accessor) => ModelMut::#variant_name(#variant_model_mut(value)), + }); } - quote! { - match value[#tag].as_str() { - #tag_variants - _ => Model::Error(value), - } - } + ( + quote! { + match value[#tag].as_str() { + #tag_variants + _ => Model::Error(value), + } + }, + quote! { + match value[#tag].as_str() { + #tag_variants_mut + _ => ModelMut::Error(value), + } + }, + ) } } else { let mut tag_variants = TokenStream::new(); + let mut tag_variants_mut = TokenStream::new(); for variant in &ast.variants { let variant_name = &variant.ident; let variant_model = Ident::new(&format!("{}Model", variant_name), variant_name.span()); + let variant_model_mut = + Ident::new(&format!("{}ModelMut", variant_name), variant_name.span()); let variant_accessor = get_accessor(&serde_rename_all, &variant.attrs, variant_name); tag_variants.extend(quote_spanned! { variant_name.span() => if value.as_object().map(|o| o.contains_key(#variant_accessor)).unwrap_or(false) { - Model::#variant_name(#variant_model(value)) + Model::#variant_name(#variant_model(value[#variant_accessor].clone())) + } else + }); + tag_variants_mut.extend(quote_spanned! { variant_name.span() => + if value.as_object().map(|o| o.contains_key(#variant_accessor)).unwrap_or(false) { + ModelMut::#variant_name(#variant_model_mut(&mut value[#variant_accessor])) } else }); } - quote! { - #tag_variants { - Model::Error(value), - } - } + ( + quote! { + #tag_variants { + Model::Error(value), + } + }, + quote! { + #tag_variants_mut { + ModelMut::Error(value), + } + }, + ) }; for variant in &ast.variants { let name = &variant.ident; let model_name = Ident::new(&format!("{}Model", variant.ident), variant.ident.span()); + let model_name_mut = + Ident::new(&format!("{}ModelMut", variant.ident), variant.ident.span()); let serde_rename_all = variant .attrs .iter() @@ -434,7 +542,10 @@ fn build_model_enum(base: &DeriveInput, ast: &DataEnum, module_name: Option None, }); model_variants.extend(quote_spanned! { name.span() => - #name(#model_name<'a>), + #name(#model_name), + }); + mut_model_variants.extend(quote_spanned! { name.span() => + #name(#model_name_mut<'a>), }); let children: Vec<_> = ChildInfo::from_fields(&serde_rename_all, &variant.fields) .into_iter() @@ -445,82 +556,154 @@ fn build_model_enum(base: &DeriveInput, ast: &DataEnum, module_name: Option #[derive(Debug)] - pub struct #model_name<'a>(&'a mut patch_db::Value); - impl<'a> ::core::ops::Deref for #model_name<'a> { + pub struct #model_name(patch_db::Value); + impl ::core::ops::Deref for #model_name { + type Target = patch_db::Value; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl ::core::ops::DerefMut for #model_name { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + impl #model_name { + #impl_fns + } + + #[derive(Debug)] + pub struct #model_name_mut<'a>(&'a mut patch_db::Value); + impl<'a> ::core::ops::Deref for #model_name_mut<'a> { type Target = patch_db::Value; fn deref(&self) -> &Self::Target { &*self.0 } } - impl<'a> ::core::ops::DerefMut for #model_name<'a> { + impl<'a> ::core::ops::DerefMut for #model_name_mut<'a> { fn deref_mut(&mut self) -> &mut Self::Target { self.0 } } - impl<'a> #model_name<'a> { - #impl_fns + impl<'a> #model_name_mut<'a> { + #impl_mut_fns } }); into_inner.extend(quote_spanned! { name.span() => Model::#name(a) => a.0, }); deref.extend(quote_spanned! { name.span() => - Model::#name(a) => &*a, + Model::#name(a) => &a.0, }); deref_mut.extend(quote_spanned! { name.span() => - Model::#name(a) => &mut *a, + Model::#name(a) => &mut a.0, + }); + mut_into_inner.extend(quote_spanned! { name.span() => + ModelMut::#name(a) => a.0, + }); + mut_deref.extend(quote_spanned! { name.span() => + ModelMut::#name(a) => &*a, + }); + mut_deref_mut.extend(quote_spanned! { name.span() => + ModelMut::#name(a) => &mut *a, }); } let name = &base.ident; let vis = &base.vis; - let impl_fns = impl_fns(&children); + let Fns { + impl_fns, + impl_mut_fns, + } = impl_fns(&children); quote! { - impl<'a> patch_db::HasModel<'a> for #name { - type Model = #module_name::Model<'a>; + impl patch_db::HasModel for #name { + type Model = #module_name::Model; } #vis mod #module_name { use super::*; #[derive(Debug)] - pub enum Model<'a> { + pub enum Model { #model_variants - Error(&'a mut patch_db::Value), + Error(patch_db::Value), } - impl<'a> patch_db::Model<'a> for Model<'a> { + impl patch_db::Model for Model { type T = #name; - fn new(value: &'a mut patch_db::Value) -> Self { + type Mut<'a> = ModelMut<'a>; + fn new(value: patch_db::Value) -> Self { #impl_new } - fn into_inner(self) -> &'a mut patch_db::Value { + fn into_inner(self) -> patch_db::Value { match self { #into_inner Model::Error(a) => a, } } } - impl<'a> ::core::ops::Deref for Model<'a> { + impl ::core::ops::Deref for Model { type Target = patch_db::Value; fn deref(&self) -> &Self::Target { match self { #deref - Model::Error(a) => &*a, + Model::Error(a) => &a, } } } - impl<'a> ::core::ops::DerefMut for Model<'a> { + impl ::core::ops::DerefMut for Model { fn deref_mut(&mut self) -> &mut Self::Target { match self { #deref_mut - Model::Error(a) => a, + Model::Error(a) => &mut a, } } } - impl<'a> Model<'a> { + impl Model { #impl_fns } + + #[derive(Debug)] + pub enum ModelMut<'a> { + #mut_model_variants + Error(&'a mut patch_db::Value), + } + impl<'a> patch_db::ModelMut<'a> for ModelMut<'a> { + type T = #name; + fn new(value: &'a mut patch_db::Value) -> Self { + #impl_new_mut + } + fn into_inner(self) -> &'a mut patch_db::Value { + match self { + #mut_into_inner + ModelMut::Error(a) => a, + } + } + } + impl<'a> ::core::ops::Deref for ModelMut<'a> { + type Target = patch_db::Value; + fn deref(&self) -> &Self::Target { + match self { + #mut_deref + ModelMut::Error(a) => &*a, + } + } + } + impl<'a> ::core::ops::DerefMut for ModelMut<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + match self { + #mut_deref_mut + ModelMut::Error(a) => a, + } + } + } + impl<'a> ModelMut<'a> { + #impl_mut_fns + } + #decl_model_variants } } diff --git a/patch-db/src/lib.rs b/patch-db/src/lib.rs index d0d9040..9586093 100644 --- a/patch-db/src/lib.rs +++ b/patch-db/src/lib.rs @@ -16,7 +16,9 @@ mod test; pub use imbl_value as value; pub use imbl_value::Value; -pub use model::{GenericModel, HasModel, Map, MapModel, Model, OptionModel}; +pub use model::{ + GenericModel, GenericModelMut, HasModel, Model, ModelMut, OptionModel, OptionModelMut, +}; pub use patch::{DiffPatch, Dump, Revision}; pub use patch_db_macro::HasModel; pub use store::{PatchDb, Store}; diff --git a/patch-db/src/model.rs b/patch-db/src/model.rs index e38b759..a72298b 100644 --- a/patch-db/src/model.rs +++ b/patch-db/src/model.rs @@ -1,16 +1,34 @@ -use std::collections::{BTreeMap, BTreeSet}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use imbl_value::Value; -use serde::de::{DeserializeOwned, Error}; +use serde::de::DeserializeOwned; use serde::Serialize; -pub trait HasModel<'a> { - type Model: Model<'a>; +pub trait HasModel { + type Model: Model; } -pub trait Model<'a>: Deref + DerefMut { +pub trait Model: Deref + DerefMut { + type T: DeserializeOwned + Serialize; + type Mut<'a>: ModelMut<'a> + where + Self: 'a; + fn new(value: Value) -> Self; + fn into_inner(self) -> Value; + fn as_mut<'a>(&'a mut self) -> Self::Mut<'a> { + Self::Mut::new(&mut *self) + } + fn set(&mut self, value: &Self::T) -> Result<(), imbl_value::Error> { + *self.deref_mut() = imbl_value::to_value(value)?; + Ok(()) + } + fn get(&self) -> Result { + imbl_value::from_value(self.deref().clone()) + } +} + +pub trait ModelMut<'a>: Deref + DerefMut { type T: DeserializeOwned + Serialize; fn new(value: &'a mut Value) -> Self; fn into_inner(self) -> &'a mut Value; @@ -23,25 +41,54 @@ pub trait Model<'a>: Deref + DerefMut { } } -pub struct GenericModel<'a, T> { +pub struct GenericModel { + value: Value, + phantom: PhantomData, +} +impl Deref for GenericModel { + type Target = Value; + fn deref(&self) -> &Self::Target { + &self.value + } +} +impl DerefMut for GenericModel { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.value + } +} +impl Model for GenericModel { + type T = T; + type Mut<'a> = GenericModelMut<'a, T> where T: 'a; + fn new(value: Value) -> Self { + Self { + value, + phantom: PhantomData, + } + } + fn into_inner(self) -> Value { + self.value + } +} + +pub struct GenericModelMut<'a, T> { value: &'a mut Value, phantom: PhantomData, } -impl<'a, T> Deref for GenericModel<'a, T> { +impl<'a, T> Deref for GenericModelMut<'a, T> { type Target = Value; fn deref(&self) -> &Self::Target { &*self.value } } -impl<'a, T> DerefMut for GenericModel<'a, T> { +impl<'a, T> DerefMut for GenericModelMut<'a, T> { fn deref_mut(&mut self) -> &mut Self::Target { self.value } } -impl<'a, T: DeserializeOwned + Serialize> Model<'a> for GenericModel<'a, T> { +impl<'a, T: DeserializeOwned + Serialize> ModelMut<'a> for GenericModelMut<'a, T> { type T = T; fn new(value: &'a mut Value) -> Self { - GenericModel { + Self { value, phantom: PhantomData, } @@ -51,167 +98,78 @@ impl<'a, T: DeserializeOwned + Serialize> Model<'a> for GenericModel<'a, T> { } } -pub trait Map<'a>: DeserializeOwned + Serialize { - type Key: AsRef; - type Value: HasModel<'a>; - fn get(&self, key: &Self::Key) -> Option<&Self::Value>; -} - -pub struct MapModel<'a, T: Map<'a>> { - value: &'a mut Value, +pub struct OptionModel { + value: Value, phantom: PhantomData, } -impl<'a, T: Map<'a>> Deref for MapModel<'a, T> { - type Target = Value; - fn deref(&self) -> &Self::Target { - &*self.value - } -} -impl<'a, T: Map<'a>> DerefMut for MapModel<'a, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.value - } -} -impl<'a, T: Map<'a>> Model<'a> for MapModel<'a, T> { - type T = T; - fn new(value: &'a mut Value) -> Self { - MapModel { - value, - phantom: PhantomData, - } - } - fn into_inner(self) -> &'a mut Value { - self.value - } -} -impl<'a, T: Map<'a>> MapModel<'a, T> { - pub fn idx(self, key: &T::Key) -> Option<>::Model> { - match self.value { - Value::Object(o) => o - .get_mut(key.as_ref()) - .map(>::Model::new), - _ => None, - } - } -} -impl<'a, T: Map<'a>> MapModel<'a, T> -where - T::Value: Serialize, -{ - pub fn put(&'a mut self, key: &T::Key, value: &T::Value) -> Result<(), imbl_value::Error> { - if let Some(o) = self.value.as_object_mut() { - o.insert(key.as_ref().to_owned().into(), imbl_value::to_value(value)?); - Ok(()) - } else { - Err(imbl_value::Error::custom("expected object")) - } - } -} -impl<'a, T: Map<'a>> MapModel<'a, T> -where - T::Key: DeserializeOwned + Ord + Eq, -{ - pub fn keys(&self) -> Result, imbl_value::Error> { - self.as_object() - .into_iter() - .flat_map(|o| o.keys()) - .cloned() - .map(|k| imbl_value::from_value(Value::String(k))) - .collect() - } - pub fn entries( - &'a mut self, - ) -> Result::Model>, imbl_value::Error> { - self.as_object_mut() - .into_iter() - .flat_map(|o| o.iter_mut()) - .map(|(k, v)| { - Ok(( - imbl_value::from_value(Value::String(k.clone()))?, - ::Model::new(v), - )) - }) - .collect() - } -} -pub struct NullRef<'a, T> { - value: Option<&'a mut Value>, - phantom: PhantomData, -} -impl<'a, T: Model<'a>> NullRef<'a, T> { - pub fn set(self, value: &T::T) -> Result<(), imbl_value::Error> { - *self.value.unwrap() = imbl_value::to_value(value)?; - Ok(()) - } -} - -pub enum OptionModel<'a, T: Model<'a>> { - Some(T), - None(NullRef<'a, T>), -} -impl<'a, T: Model<'a> + 'a> OptionModel<'a, T> { +impl OptionModel { pub fn check(self) -> Option { - match self { - OptionModel::Some(a) => Some(a), - _ => None, + if self.is_null() { + None + } else { + Some(T::new(self.value)) } } } -impl<'a, T: Model<'a>> Deref for OptionModel<'a, T> { +impl Deref for OptionModel { type Target = Value; fn deref(&self) -> &Self::Target { - match self { - OptionModel::None(a) => &*a.value.as_ref().unwrap(), - OptionModel::Some(a) => &**a, - } + &self.value } } -impl<'a, T: Model<'a>> DerefMut for OptionModel<'a, T> { +impl DerefMut for OptionModel { fn deref_mut(&mut self) -> &mut Self::Target { - match self { - OptionModel::None(a) => &mut *a.value.as_mut().unwrap(), - OptionModel::Some(a) => &mut *a, + &mut self.value + } +} +impl Model for OptionModel { + type T = Option; + type Mut<'a> = OptionModelMut<'a, T::Mut<'a>> where T: 'a; + fn new(value: Value) -> Self { + Self { + value, + phantom: PhantomData, + } + } + fn into_inner(self) -> Value { + self.value + } +} + +pub struct OptionModelMut<'a, T: ModelMut<'a>> { + value: &'a mut Value, + phantom: PhantomData, +} +impl<'a, T: ModelMut<'a>> OptionModelMut<'a, T> { + pub fn check(self) -> Option { + if self.is_null() { + None + } else { + Some(T::new(self.value)) } } } -impl<'a, T: Model<'a>> Model<'a> for OptionModel<'a, T> { +impl<'a, T: ModelMut<'a>> Deref for OptionModelMut<'a, T> { + type Target = Value; + fn deref(&self) -> &Self::Target { + &*self.value + } +} +impl<'a, T: ModelMut<'a>> DerefMut for OptionModelMut<'a, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.value + } +} +impl<'a, T: ModelMut<'a>> ModelMut<'a> for OptionModelMut<'a, T> { type T = Option; fn new(value: &'a mut Value) -> Self { - if value.is_null() { - OptionModel::None(NullRef { - value: Some(value), - phantom: PhantomData, - }) - } else { - OptionModel::Some(T::new(value)) + Self { + value, + phantom: PhantomData, } } fn into_inner(self) -> &'a mut Value { - match self { - OptionModel::None(a) => a.value.unwrap(), - OptionModel::Some(a) => a.into_inner(), - } - } - fn set(&mut self, value: &Self::T) -> Result<(), imbl_value::Error> { - let value = imbl_value::to_value(value)?; - let old = std::mem::replace( - self, - OptionModel::None(NullRef { - value: None, - phantom: PhantomData, - }), - ) - .into_inner(); - *old = value; - *self = if old.is_null() { - OptionModel::None(NullRef { - value: Some(old), - phantom: PhantomData, - }) - } else { - OptionModel::Some(T::new(old)) - }; - Ok(()) + self.value } } diff --git a/patch-db/src/store.rs b/patch-db/src/store.rs index 7956ba6..afa226d 100644 --- a/patch-db/src/store.rs +++ b/patch-db/src/store.rs @@ -352,27 +352,22 @@ impl PatchDb { let rev = store.apply(patch).await?; Ok(rev) } - pub async fn apply_func(&self, f: F) -> Result + pub async fn apply_function(&self, f: F) -> Result<(Value, T), E> where - F: FnOnce(&mut Value) -> Result + UnwindSafe, + F: FnOnce(Value) -> Result<(Value, T), E> + UnwindSafe, E: From, { let mut store = self.store.write().await; - let mut old = store.persistent.clone(); - let (new, res) = std::panic::catch_unwind(move || { - let res = f(&mut old); - (old, res) - }) - .map_err(|e| { + let old = store.persistent.clone(); + let (new, res) = std::panic::catch_unwind(move || f(old)).map_err(|e| { Error::Panick( e.downcast() .map(|a| *a) .unwrap_or_else(|_| "UNKNOWN".to_owned()), ) - })?; - let res = res?; + })??; let diff = diff(&store.persistent, &new); store.apply(diff).await?; - Ok(res) + Ok((new, res)) } }