diff --git a/.github/test.sh b/.github/test.sh index 2fdbf58b9..6fea5344c 100755 --- a/.github/test.sh +++ b/.github/test.sh @@ -15,6 +15,8 @@ pushd borsh cargo test --no-run cargo test cargo test --features derive +cargo test --features derive,unstable__tokio +cargo test --features derive,unstable__async-std cargo test --features unstable__schema ########## features = ["ascii"] group cargo test --features ascii 'roundtrip::test_ascii_strings' diff --git a/borsh-derive/src/internals/attributes/field/bounds.rs b/borsh-derive/src/internals/attributes/field/bounds.rs index d383b2327..261a354e5 100644 --- a/borsh-derive/src/internals/attributes/field/bounds.rs +++ b/borsh-derive/src/internals/attributes/field/bounds.rs @@ -1,9 +1,9 @@ use std::collections::BTreeMap; +use once_cell::sync::Lazy; use syn::{meta::ParseNestedMeta, WherePredicate}; use crate::internals::attributes::{parsing::parse_lit_into_vec, Symbol, DESERIALIZE, SERIALIZE}; -use once_cell::sync::Lazy; pub enum Variants { Serialize(Vec), diff --git a/borsh-derive/src/internals/attributes/field/mod.rs b/borsh-derive/src/internals/attributes/field/mod.rs index 0ff2555c1..739059c29 100644 --- a/borsh-derive/src/internals/attributes/field/mod.rs +++ b/borsh-derive/src/internals/attributes/field/mod.rs @@ -2,19 +2,18 @@ use std::collections::BTreeMap; use once_cell::sync::Lazy; use syn::{meta::ParseNestedMeta, Attribute, WherePredicate}; +#[cfg(feature = "schema")] +use { + super::schema_keys::{PARAMS, SCHEMA, WITH_FUNCS}, + schema::SCHEMA_FIELD_PARSE_MAP, +}; use self::bounds::BOUNDS_FIELD_PARSE_MAP; - use super::{ get_one_attribute, parsing::{attr_get_by_symbol_keys, meta_get_by_symbol_keys, parse_lit_into}, - BoundType, Symbol, BORSH, BOUND, DESERIALIZE_WITH, SERIALIZE_WITH, SKIP, -}; - -#[cfg(feature = "schema")] -use { - super::schema_keys::{PARAMS, SCHEMA, WITH_FUNCS}, - schema::SCHEMA_FIELD_PARSE_MAP, + BoundType, Symbol, ASYNC_BOUND, BORSH, BOUND, DESERIALIZE_WITH, DESERIALIZE_WITH_ASYNC, + SERIALIZE_WITH, SERIALIZE_WITH_ASYNC, SKIP, }; pub mod bounds; @@ -25,6 +24,8 @@ enum Variants { Bounds(bounds::Bounds), SerializeWith(syn::ExprPath), DeserializeWith(syn::ExprPath), + SerializeWithAsync(syn::ExprPath), + DeserializeWithAsync(syn::ExprPath), Skip(()), #[cfg(feature = "schema")] Schema(schema::Attributes), @@ -42,6 +43,12 @@ static BORSH_FIELD_PARSE_MAP: Lazy>> = Lazy::new(| Ok(Variants::Bounds(bounds_attributes)) }); + let f_async_bounds: Box = Box::new(|_attr_name, _meta_item_name, meta| { + let map_result = meta_get_by_symbol_keys(ASYNC_BOUND, meta, &BOUNDS_FIELD_PARSE_MAP)?; + let bounds_attributes: bounds::Bounds = map_result.into(); + Ok(Variants::Bounds(bounds_attributes)) + }); + let f_serialize_with: Box = Box::new(|attr_name, meta_item_name, meta| { parse_lit_into::(attr_name, meta_item_name, meta) .map(Variants::SerializeWith) @@ -52,6 +59,16 @@ static BORSH_FIELD_PARSE_MAP: Lazy>> = Lazy::new(| .map(Variants::DeserializeWith) }); + let f_serialize_with_async: Box = Box::new(|attr_name, meta_item_name, meta| { + parse_lit_into::(attr_name, meta_item_name, meta) + .map(Variants::SerializeWithAsync) + }); + + let f_deserialize_with_async: Box = Box::new(|attr_name, meta_item_name, meta| { + parse_lit_into::(attr_name, meta_item_name, meta) + .map(Variants::DeserializeWithAsync) + }); + #[cfg(feature = "schema")] let f_schema: Box = Box::new(|_attr_name, _meta_item_name, meta| { let map_result = meta_get_by_symbol_keys(SCHEMA, meta, &SCHEMA_FIELD_PARSE_MAP)?; @@ -62,8 +79,11 @@ static BORSH_FIELD_PARSE_MAP: Lazy>> = Lazy::new(| let f_skip: Box = Box::new(|_attr_name, _meta_item_name, _meta| Ok(Variants::Skip(()))); m.insert(BOUND, f_bounds); + m.insert(ASYNC_BOUND, f_async_bounds); m.insert(SERIALIZE_WITH, f_serialize_with); m.insert(DESERIALIZE_WITH, f_deserialize_with); + m.insert(SERIALIZE_WITH_ASYNC, f_serialize_with_async); + m.insert(DESERIALIZE_WITH_ASYNC, f_deserialize_with_async); m.insert(SKIP, f_skip); #[cfg(feature = "schema")] m.insert(SCHEMA, f_schema); @@ -73,8 +93,11 @@ static BORSH_FIELD_PARSE_MAP: Lazy>> = Lazy::new(| #[derive(Default, Clone)] pub(crate) struct Attributes { pub bounds: Option, + pub async_bounds: Option, pub serialize_with: Option, pub deserialize_with: Option, + pub serialize_with_async: Option, + pub deserialize_with_async: Option, pub skip: bool, #[cfg(feature = "schema")] pub schema: Option, @@ -83,14 +106,23 @@ pub(crate) struct Attributes { impl From> for Attributes { fn from(mut map: BTreeMap) -> Self { let bounds = map.remove(&BOUND); + let async_bounds = map.remove(&ASYNC_BOUND); let serialize_with = map.remove(&SERIALIZE_WITH); let deserialize_with = map.remove(&DESERIALIZE_WITH); + let serialize_with_async = map.remove(&SERIALIZE_WITH_ASYNC); + let deserialize_with_async = map.remove(&DESERIALIZE_WITH_ASYNC); let skip = map.remove(&SKIP); + let bounds = bounds.map(|variant| match variant { Variants::Bounds(bounds) => bounds, _ => unreachable!("only one enum variant is expected to correspond to given map key"), }); + let async_bounds = async_bounds.map(|variant| match variant { + Variants::Bounds(bounds) => bounds, + _ => unreachable!("only one enum variant is expected to correspond to given map key"), + }); + let serialize_with = serialize_with.map(|variant| match variant { Variants::SerializeWith(serialize_with) => serialize_with, _ => unreachable!("only one enum variant is expected to correspond to given map key"), @@ -101,6 +133,16 @@ impl From> for Attributes { _ => unreachable!("only one enum variant is expected to correspond to given map key"), }); + let serialize_with_async = serialize_with_async.map(|variant| match variant { + Variants::SerializeWithAsync(serialize_with_async) => serialize_with_async, + _ => unreachable!("only one enum variant is expected to correspond to given map key"), + }); + + let deserialize_with_async = deserialize_with_async.map(|variant| match variant { + Variants::DeserializeWithAsync(deserialize_with_async) => deserialize_with_async, + _ => unreachable!("only one enum variant is expected to correspond to given map key"), + }); + let skip = skip.map(|variant| match variant { Variants::Skip(skip) => skip, _ => unreachable!("only one enum variant is expected to correspond to given map key"), @@ -116,10 +158,14 @@ impl From> for Attributes { } }) }; + Self { bounds, + async_bounds, serialize_with, deserialize_with, + serialize_with_async, + deserialize_with_async, skip: skip.is_some(), #[cfg(feature = "schema")] schema, @@ -136,12 +182,21 @@ pub(crate) fn filter_attrs( impl Attributes { fn check(&self, attr: &Attribute) -> Result<(), syn::Error> { - if self.skip && (self.serialize_with.is_some() || self.deserialize_with.is_some()) { + if self.skip + && (self.serialize_with.is_some() + || self.deserialize_with.is_some() + || self.serialize_with_async.is_some() + || self.deserialize_with_async.is_some()) + { return Err(syn::Error::new_spanned( attr, format!( - "`{}` cannot be used at the same time as `{}` or `{}`", - SKIP.0, SERIALIZE_WITH.0, DESERIALIZE_WITH.0 + "`{}` cannot be used at the same time as `{}`, `{}`, `{}` or `{}`", + SKIP.name, + SERIALIZE_WITH.name, + DESERIALIZE_WITH.name, + SERIALIZE_WITH_ASYNC.name, + DESERIALIZE_WITH_ASYNC.name ), )); } @@ -151,6 +206,7 @@ impl Attributes { Ok(()) } + pub(crate) fn parse(attrs: &[Attribute]) -> Result { let borsh = get_one_attribute(attrs)?; @@ -164,11 +220,17 @@ impl Attributes { Ok(result) } + pub(crate) fn needs_bounds_derive(&self, ty: BoundType) -> bool { let predicates = self.get_bounds(ty); predicates.is_none() } + pub(crate) fn needs_async_bounds_derive(&self, ty: BoundType) -> bool { + let predicates = self.get_async_bounds(ty); + predicates.is_none() + } + fn get_bounds(&self, ty: BoundType) -> Option> { let bounds = self.bounds.as_ref(); bounds.and_then(|bounds| match ty { @@ -176,10 +238,24 @@ impl Attributes { BoundType::Deserialize => bounds.deserialize.clone(), }) } + + fn get_async_bounds(&self, ty: BoundType) -> Option> { + let bounds = self.async_bounds.as_ref(); + bounds.and_then(|bounds| match ty { + BoundType::Serialize => bounds.serialize.clone(), + BoundType::Deserialize => bounds.deserialize.clone(), + }) + } + pub(crate) fn collect_bounds(&self, ty: BoundType) -> Vec { let predicates = self.get_bounds(ty); predicates.unwrap_or_default() } + + pub(crate) fn collect_async_bounds(&self, ty: BoundType) -> Vec { + let predicates = self.get_async_bounds(ty); + predicates.unwrap_or_default() + } } #[cfg(feature = "schema")] @@ -191,7 +267,7 @@ impl Attributes { attr, format!( "`{}` cannot be used at the same time as `{}({})`", - SKIP.0, SCHEMA.0, PARAMS.1 + SKIP.name, SCHEMA.name, PARAMS.expected ), )); } @@ -201,7 +277,7 @@ impl Attributes { attr, format!( "`{}` cannot be used at the same time as `{}({})`", - SKIP.0, SCHEMA.0, WITH_FUNCS.1 + SKIP.name, SCHEMA.name, WITH_FUNCS.expected ), )); } @@ -239,25 +315,31 @@ impl Attributes { #[cfg(test)] mod tests { - use quote::quote; - use syn::{Attribute, ItemStruct}; - - fn parse_bounds(attrs: &[Attribute]) -> Result, syn::Error> { - // #[borsh(bound(serialize = "...", deserialize = "..."))] - let borsh_attrs = Attributes::parse(attrs)?; - Ok(borsh_attrs.bounds) - } + use syn::{parse_quote, Attribute, ItemStruct}; + use super::{bounds, Attributes}; use crate::internals::test_helpers::{ debug_print_tokenizable, debug_print_vec_of_tokenizable, local_insta_assert_debug_snapshot, local_insta_assert_snapshot, }; - use super::{bounds, Attributes}; + struct ParsedBounds { + common: Option, + r#async: Option, + } + + fn parse_bounds(attrs: &[Attribute]) -> Result { + // #[borsh(bound(serialize = "...", deserialize = "..."), async_bound(serialize = "...", deserialize = "..."))] + let borsh_attrs = Attributes::parse(attrs)?; + Ok(ParsedBounds { + common: borsh_attrs.bounds, + r#async: borsh_attrs.async_bounds, + }) + } #[test] fn test_reject_multiple_borsh_attrs() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(skip)] #[borsh(bound(deserialize = "K: Hash + Ord, @@ -268,8 +350,7 @@ mod tests { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let err = match Attributes::parse(&first_field.attrs) { @@ -281,7 +362,7 @@ mod tests { #[test] fn test_bounds_parsing1() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deserialize = "K: Hash + Ord, V: Eq + Ord", @@ -291,18 +372,17 @@ mod tests { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().unwrap(); - local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize.clone())); + let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize)); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } #[test] fn test_bounds_parsing2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deserialize = "K: Hash + Eq + borsh::de::BorshDeserialize, V: borsh::de::BorshDeserialize", @@ -312,18 +392,17 @@ mod tests { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().unwrap(); - local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize.clone())); + let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize)); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } #[test] fn test_bounds_parsing3() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deserialize = "K: Hash + Eq + borsh::de::BorshDeserialize, V: borsh::de::BorshDeserialize", @@ -332,42 +411,39 @@ mod tests { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().unwrap(); + let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); assert_eq!(attrs.serialize.as_ref().unwrap().len(), 0); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } #[test] fn test_bounds_parsing4() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deserialize = "K: Hash"))] x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().unwrap(); + let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); assert!(attrs.serialize.is_none()); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } #[test] fn test_bounds_parsing_error() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deser = "K: Hash"))] x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let err = match parse_bounds(&first_field.attrs) { @@ -379,14 +455,13 @@ mod tests { #[test] fn test_bounds_parsing_error2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deserialize = "K Hash"))] x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let err = match parse_bounds(&first_field.attrs) { @@ -398,14 +473,148 @@ mod tests { #[test] fn test_bounds_parsing_error3() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deserialize = 42))] x: u64, y: String, } - }) - .unwrap(); + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let err = match parse_bounds(&first_field.attrs) { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); + } + + #[test] + fn test_async_bounds_parsing1() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(async_bound( + deserialize = + "K: Hash + Ord, + V: Eq + Ord", + serialize = + "K: Hash + Eq + Ord, + V: Ord" + ))] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let attrs = parse_bounds(&first_field.attrs).unwrap().r#async.unwrap(); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize)); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); + } + + #[test] + fn test_async_bounds_parsing2() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(async_bound(deserialize = + "K: Hash + Eq + borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync", + serialize = + "K: Hash + Eq + borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync" + ))] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let attrs = parse_bounds(&first_field.attrs).unwrap().r#async.unwrap(); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize)); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); + } + + #[test] + fn test_async_bounds_parsing3() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(async_bound(deserialize = + "K: Hash + Eq + borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync", + serialize = "" + ))] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let attrs = parse_bounds(&first_field.attrs).unwrap().r#async.unwrap(); + assert_eq!(attrs.serialize.as_ref().unwrap().len(), 0); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); + } + + #[test] + fn test_async_bounds_parsing4() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(async_bound(deserialize = "K: Hash"))] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let attrs = parse_bounds(&first_field.attrs).unwrap().r#async.unwrap(); + assert!(attrs.serialize.is_none()); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); + } + + #[test] + fn test_async_bounds_parsing_error() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(async_bound(deser = "K: Hash"))] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let err = match parse_bounds(&first_field.attrs) { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); + } + + #[test] + fn test_async_bounds_parsing_error2() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(async_bound(deserialize = "K Hash"))] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let err = match parse_bounds(&first_field.attrs) { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); + } + + #[test] + fn test_async_bounds_parsing_error3() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(async_bound(deserialize = 42))] + x: u64, + y: String, + } + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let err = match parse_bounds(&first_field.attrs) { @@ -417,7 +626,7 @@ mod tests { #[test] fn test_ser_de_with_parsing1() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh( serialize_with = "third_party_impl::serialize_third_party", @@ -426,39 +635,57 @@ mod tests { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let attrs = Attributes::parse(&first_field.attrs).unwrap(); local_insta_assert_snapshot!(debug_print_tokenizable(attrs.serialize_with.as_ref())); local_insta_assert_snapshot!(debug_print_tokenizable(attrs.deserialize_with)); } + + #[test] + fn test_async_ser_de_with_parsing1() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh( + serialize_with_async = "third_party_impl::serialize_third_party", + deserialize_with_async = "third_party_impl::deserialize_third_party", + )] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let attrs = Attributes::parse(&first_field.attrs).unwrap(); + local_insta_assert_snapshot!(debug_print_tokenizable(attrs.serialize_with_async.as_ref())); + local_insta_assert_snapshot!(debug_print_tokenizable(attrs.deserialize_with_async)); + } + #[test] fn test_borsh_skip() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(skip)] x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let result = Attributes::parse(&first_field.attrs).unwrap(); assert!(result.skip); } + #[test] fn test_borsh_no_skip() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; @@ -470,6 +697,9 @@ mod tests { #[cfg(feature = "schema")] #[cfg(test)] mod tests_schema { + use syn::{parse_quote, Attribute, ItemStruct}; + + use super::schema; use crate::internals::{ attributes::field::Attributes, test_helpers::{ @@ -478,10 +708,6 @@ mod tests_schema { }, }; - use quote::quote; - use syn::{Attribute, ItemStruct}; - - use super::schema; fn parse_schema_attrs(attrs: &[Attribute]) -> Result, syn::Error> { // #[borsh(schema(params = "..."))] let borsh_attrs = Attributes::parse(attrs)?; @@ -490,7 +716,7 @@ mod tests_schema { #[test] fn test_root_bounds_and_params_combined() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh( serialize_with = "third_party_impl::serialize_third_party", @@ -500,8 +726,7 @@ mod tests_schema { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; @@ -511,13 +736,13 @@ mod tests_schema { local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(bounds.deserialize)); assert!(attrs.deserialize_with.is_none()); let schema = attrs.schema.clone().unwrap(); - local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(schema.params.clone())); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(schema.params)); local_insta_assert_snapshot!(debug_print_tokenizable(attrs.serialize_with)); } #[test] fn test_schema_params_parsing1() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -528,16 +753,16 @@ mod tests_schema { field: ::Associated, another: V, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let schema_attrs = parse_schema_attrs(&first_field.attrs).unwrap(); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(schema_attrs.unwrap().params)); } + #[test] fn test_schema_params_parsing_error() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -548,8 +773,7 @@ mod tests_schema { field: ::Associated, another: V, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let err = match parse_schema_attrs(&first_field.attrs) { @@ -561,7 +785,7 @@ mod tests_schema { #[test] fn test_schema_params_parsing_error2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -572,8 +796,7 @@ mod tests_schema { field: ::Associated, another: V, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let err = match parse_schema_attrs(&first_field.attrs) { @@ -585,7 +808,7 @@ mod tests_schema { #[test] fn test_schema_params_parsing2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -596,16 +819,16 @@ mod tests_schema { field: ::Associated, another: V, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let schema_attrs = parse_schema_attrs(&first_field.attrs).unwrap(); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(schema_attrs.unwrap().params)); } + #[test] fn test_schema_params_parsing3() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -614,8 +837,7 @@ mod tests_schema { field: ::Associated, another: V, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let schema_attrs = parse_schema_attrs(&first_field.attrs).unwrap(); @@ -624,7 +846,7 @@ mod tests_schema { #[test] fn test_schema_params_parsing4() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -632,8 +854,7 @@ mod tests_schema { field: ::Associated, another: V, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let schema_attrs = parse_schema_attrs(&first_field.attrs).unwrap(); @@ -642,7 +863,7 @@ mod tests_schema { #[test] fn test_schema_with_funcs_parsing() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(schema(with_funcs( declaration = "third_party_impl::declaration::", @@ -651,22 +872,21 @@ mod tests_schema { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let attrs = Attributes::parse(&first_field.attrs).unwrap(); let schema = attrs.schema.unwrap(); let with_funcs = schema.with_funcs.unwrap(); - local_insta_assert_snapshot!(debug_print_tokenizable(with_funcs.declaration.clone())); + local_insta_assert_snapshot!(debug_print_tokenizable(with_funcs.declaration)); local_insta_assert_snapshot!(debug_print_tokenizable(with_funcs.definitions)); } // both `declaration` and `definitions` have to be specified #[test] fn test_schema_with_funcs_parsing_error() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(schema(with_funcs( declaration = "third_party_impl::declaration::" @@ -674,8 +894,7 @@ mod tests_schema { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let attrs = Attributes::parse(&first_field.attrs); @@ -689,14 +908,13 @@ mod tests_schema { #[test] fn test_root_error() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(boons)] x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; let err = match Attributes::parse(&first_field.attrs) { @@ -708,7 +926,7 @@ mod tests_schema { #[test] fn test_root_bounds_and_wrong_key_combined() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(bound(deserialize = "K: Hash"), schhema(params = "T => ::Associated, V => Vec") @@ -716,8 +934,7 @@ mod tests_schema { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; diff --git a/borsh-derive/src/internals/attributes/field/schema.rs b/borsh-derive/src/internals/attributes/field/schema.rs index 40ebec39d..32210c7b1 100644 --- a/borsh-derive/src/internals/attributes/field/schema.rs +++ b/borsh-derive/src/internals/attributes/field/schema.rs @@ -1,10 +1,5 @@ use std::collections::BTreeMap; -use crate::internals::attributes::{ - parsing::{meta_get_by_symbol_keys, parse_lit_into_vec}, - schema_keys::{DECLARATION, DEFINITIONS, PARAMS, WITH_FUNCS}, - Symbol, -}; use once_cell::sync::Lazy; use quote::ToTokens; use syn::{ @@ -14,6 +9,11 @@ use syn::{ }; use self::with_funcs::{WithFuncs, WITH_FUNCS_FIELD_PARSE_MAP}; +use crate::internals::attributes::{ + parsing::{meta_get_by_symbol_keys, parse_lit_into_vec}, + schema_keys::{DECLARATION, DEFINITIONS, PARAMS, WITH_FUNCS}, + Symbol, +}; pub mod with_funcs; @@ -43,7 +43,7 @@ pub static SCHEMA_FIELD_PARSE_MAP: Lazy>> = Lazy:: &meta.path, format!( "both `{}` and `{}` have to be specified at the same time", - DECLARATION.1, DEFINITIONS.1, + DECLARATION.expected, DEFINITIONS.expected, ), )); } diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1-2.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1-2.snap new file mode 100644 index 000000000..75ee80942 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1-2.snap @@ -0,0 +1,6 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_vec_of_tokenizable(attrs.deserialize) +--- +K : Hash + Ord +V : Eq + Ord diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1.snap new file mode 100644 index 000000000..182ab0ab3 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1.snap @@ -0,0 +1,6 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_vec_of_tokenizable(attrs.serialize) +--- +K : Hash + Eq + Ord +V : Ord diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2-2.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2-2.snap new file mode 100644 index 000000000..d3c7c7d51 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2-2.snap @@ -0,0 +1,6 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_vec_of_tokenizable(attrs.deserialize) +--- +K : Hash + Eq + borsh :: de :: BorshDeserializeAsync +V : borsh :: de :: BorshDeserializeAsync diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2.snap new file mode 100644 index 000000000..e27068395 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2.snap @@ -0,0 +1,6 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_vec_of_tokenizable(attrs.serialize) +--- +K : Hash + Eq + borsh :: ser :: BorshSerializeAsync +V : borsh :: ser :: BorshSerializeAsync diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing3.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing3.snap new file mode 100644 index 000000000..d3c7c7d51 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing3.snap @@ -0,0 +1,6 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_vec_of_tokenizable(attrs.deserialize) +--- +K : Hash + Eq + borsh :: de :: BorshDeserializeAsync +V : borsh :: de :: BorshDeserializeAsync diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing4.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing4.snap new file mode 100644 index 000000000..a68309c1b --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing4.snap @@ -0,0 +1,5 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_vec_of_tokenizable(attrs.deserialize) +--- +K : Hash diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error.snap new file mode 100644 index 000000000..da1748fd0 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: err +--- +Error( + "malformed async_bound attribute, expected `async_bound(deserialize = ..., serialize = ...)`", +) diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error2.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error2.snap new file mode 100644 index 000000000..fc006afe2 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error2.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: err +--- +Error( + "expected `:`", +) diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error3.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error3.snap new file mode 100644 index 000000000..36e9a0b74 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error3.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: err +--- +Error( + "expected borsh async_bound attribute to be a string: `deserialize = \"...\"`", +) diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1-2.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1-2.snap new file mode 100644 index 000000000..2ca40b4fb --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1-2.snap @@ -0,0 +1,5 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_tokenizable(attrs.deserialize_with_async) +--- +third_party_impl :: deserialize_third_party diff --git a/borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1.snap b/borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1.snap new file mode 100644 index 000000000..39366dd42 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1.snap @@ -0,0 +1,5 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: debug_print_tokenizable(attrs.serialize_with_async.as_ref()) +--- +third_party_impl :: serialize_third_party diff --git a/borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined.snap b/borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined.snap index 110f4f29f..f62d0826e 100644 --- a/borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined.snap +++ b/borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined.snap @@ -3,5 +3,5 @@ source: borsh-derive/src/internals/attributes/field/mod.rs expression: err --- Error( - "malformed borsh attribute, expected `borsh(bound(...), deserialize_with = ..., schema(...), serialize_with = ..., skip)`", + "malformed borsh attribute, expected `borsh(async_bound(...), bound(...), deserialize_with = ..., deserialize_with_async = ..., schema(...), serialize_with = ..., serialize_with_async = ..., skip)`", ) diff --git a/borsh-derive/src/internals/attributes/field/snapshots/root_error.snap b/borsh-derive/src/internals/attributes/field/snapshots/root_error.snap index 110f4f29f..f62d0826e 100644 --- a/borsh-derive/src/internals/attributes/field/snapshots/root_error.snap +++ b/borsh-derive/src/internals/attributes/field/snapshots/root_error.snap @@ -3,5 +3,5 @@ source: borsh-derive/src/internals/attributes/field/mod.rs expression: err --- Error( - "malformed borsh attribute, expected `borsh(bound(...), deserialize_with = ..., schema(...), serialize_with = ..., skip)`", + "malformed borsh attribute, expected `borsh(async_bound(...), bound(...), deserialize_with = ..., deserialize_with_async = ..., schema(...), serialize_with = ..., serialize_with_async = ..., skip)`", ) diff --git a/borsh-derive/src/internals/attributes/item/mod.rs b/borsh-derive/src/internals/attributes/item/mod.rs index ff3551486..8d25d7472 100644 --- a/borsh-derive/src/internals/attributes/item/mod.rs +++ b/borsh-derive/src/internals/attributes/item/mod.rs @@ -1,8 +1,8 @@ -use crate::internals::attributes::{BORSH, CRATE, INIT, USE_DISCRIMINANT}; use quote::ToTokens; use syn::{spanned::Spanned, Attribute, DeriveInput, Error, Expr, ItemEnum, Path}; use super::{get_one_attribute, parsing}; +use crate::internals::attributes::{BORSH, CRATE, INIT, USE_DISCRIMINANT}; pub fn check_attributes(derive_input: &DeriveInput) -> Result<(), Error> { let borsh = get_one_attribute(&derive_input.attrs)?; @@ -10,7 +10,7 @@ pub fn check_attributes(derive_input: &DeriveInput) -> Result<(), Error> { if let Some(attr) = borsh { attr.parse_nested_meta(|meta| { if meta.path != USE_DISCRIMINANT && meta.path != INIT && meta.path != CRATE { - return Err(syn::Error::new( + return Err(Error::new( meta.path.span(), "`crate`, `use_discriminant` or `init` are the only supported attributes for `borsh`", )); @@ -33,9 +33,9 @@ pub fn check_attributes(derive_input: &DeriveInput) -> Result<(), Error> { Ok(()) } -pub(crate) fn contains_use_discriminant(input: &ItemEnum) -> Result { +pub(crate) fn contains_use_discriminant(input: &ItemEnum) -> Result { if input.variants.len() > 256 { - return Err(syn::Error::new( + return Err(Error::new( input.span(), "up to 256 enum variants are supported", )); @@ -120,52 +120,50 @@ pub(crate) fn get_crate(attrs: &[Attribute]) -> Result, Error> { #[cfg(test)] mod tests { - use crate::internals::test_helpers::local_insta_assert_debug_snapshot; - use quote::{quote, ToTokens}; - use syn::ItemEnum; + use quote::ToTokens; + use syn::{parse_quote, ItemEnum}; use super::*; + use crate::internals::test_helpers::local_insta_assert_debug_snapshot; + #[test] fn test_use_discriminant() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[derive(BorshDeserialize, Debug)] #[borsh(use_discriminant = false)] enum AWithUseDiscriminantFalse { X, Y, } - }) - .unwrap(); + }; let actual = contains_use_discriminant(&item_enum); assert!(!actual.unwrap()); } #[test] fn test_use_discriminant_true() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[derive(BorshDeserialize, Debug)] #[borsh(use_discriminant = true)] enum AWithUseDiscriminantTrue { X, Y, } - }) - .unwrap(); + }; let actual = contains_use_discriminant(&item_enum); assert!(actual.unwrap()); } #[test] fn test_use_discriminant_wrong_value() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[derive(BorshDeserialize, Debug)] #[borsh(use_discriminant = 111)] enum AWithUseDiscriminantFalse { X, Y, } - }) - .unwrap(); + }; let actual = contains_use_discriminant(&item_enum); let err = match actual { Ok(..) => unreachable!("expecting error here"), @@ -175,64 +173,60 @@ mod tests { } #[test] fn test_check_attrs_use_discriminant_on_struct() { - let item_enum: DeriveInput = syn::parse2(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshDeserialize, Debug)] #[borsh(use_discriminant = false)] struct AWithUseDiscriminantFalse { x: X, y: Y, } - }) - .unwrap(); - let actual = check_attributes(&item_enum); + }; + let actual = check_attributes(&derive_input); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn test_check_attrs_borsh_skip_on_whole_item() { - let item_enum: DeriveInput = syn::parse2(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshDeserialize, Debug)] #[borsh(skip)] struct AWithUseDiscriminantFalse { x: X, y: Y, } - }) - .unwrap(); - let actual = check_attributes(&item_enum); + }; + let actual = check_attributes(&derive_input); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn test_check_attrs_borsh_invalid_on_whole_item() { - let item_enum: DeriveInput = syn::parse2(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshDeserialize, Debug)] #[borsh(invalid)] enum AWithUseDiscriminantFalse { X, Y, } - }) - .unwrap(); - let actual = check_attributes(&item_enum); + }; + let actual = check_attributes(&derive_input); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn test_check_attrs_init_function() { - let item_struct = syn::parse2::(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(init = initialization_method)] struct A<'a> { x: u64, } - }) - .unwrap(); + }; - let actual = check_attributes(&item_struct); + let actual = check_attributes(&derive_input); assert!(actual.is_ok()); } #[test] fn test_check_attrs_init_function_with_use_discriminant_reversed() { - let item_struct = syn::parse2::(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(use_discriminant=true, init = initialization_method)] enum A { @@ -240,16 +234,15 @@ mod tests { C, D= 10, } - }) - .unwrap(); + }; - let actual = check_attributes(&item_struct); + let actual = check_attributes(&derive_input); assert!(actual.is_ok()); } #[test] fn test_reject_multiple_borsh_attrs() { - let item_struct = syn::parse2::(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(use_discriminant=true)] #[borsh(init = initialization_method)] @@ -258,16 +251,15 @@ mod tests { C, D= 10, } - }) - .unwrap(); + }; - let actual = check_attributes(&item_struct); + let actual = check_attributes(&derive_input); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn test_check_attrs_init_function_with_use_discriminant() { - let item_struct = syn::parse2::(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(init = initialization_method, use_discriminant=true)] enum A { @@ -275,16 +267,15 @@ mod tests { C, D= 10, } - }) - .unwrap(); + }; - let actual = check_attributes(&item_struct); + let actual = check_attributes(&derive_input); assert!(actual.is_ok()); } #[test] fn test_check_attrs_init_function_wrong_format() { - let item_struct: DeriveInput = syn::parse2(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshDeserialize, Debug)] #[borsh(init_func = initialization_method)] struct A<'a> { @@ -295,23 +286,21 @@ mod tests { v: Vec, } - }) - .unwrap(); - let actual = check_attributes(&item_struct); + }; + let actual = check_attributes(&derive_input); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn test_init_function() { - let item_struct = syn::parse2::(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(init = initialization_method)] struct A<'a> { x: u64, } - }) - .unwrap(); + }; - let actual = contains_initialize_with(&item_struct.attrs); + let actual = contains_initialize_with(&derive_input.attrs); assert_eq!( actual.unwrap().to_token_stream().to_string(), "initialization_method" @@ -320,16 +309,15 @@ mod tests { #[test] fn test_init_function_parsing_error() { - let item_struct = syn::parse2::(quote! { + let derive_input: DeriveInput = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(init={strange; blocky})] struct A { lazy: Option, } - }) - .unwrap(); + }; - let actual = contains_initialize_with(&item_struct.attrs); + let actual = contains_initialize_with(&derive_input.attrs); let err = match actual { Ok(..) => unreachable!("expecting error here"), Err(err) => err, @@ -339,7 +327,7 @@ mod tests { #[test] fn test_init_function_with_use_discriminant() { - let item_struct = syn::parse2::(quote! { + let item_enum: ItemEnum = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(init = initialization_method, use_discriminant=true)] enum A { @@ -347,21 +335,20 @@ mod tests { C, D, } - }) - .unwrap(); + }; - let actual = contains_initialize_with(&item_struct.attrs); + let actual = contains_initialize_with(&item_enum.attrs); assert_eq!( actual.unwrap().to_token_stream().to_string(), "initialization_method" ); - let actual = contains_use_discriminant(&item_struct); + let actual = contains_use_discriminant(&item_enum); assert!(actual.unwrap()); } #[test] fn test_init_function_with_use_discriminant_reversed() { - let item_struct = syn::parse2::(quote! { + let item_enum: ItemEnum = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(use_discriminant=true, init = initialization_method)] enum A { @@ -369,21 +356,20 @@ mod tests { C, D, } - }) - .unwrap(); + }; - let actual = contains_initialize_with(&item_struct.attrs); + let actual = contains_initialize_with(&item_enum.attrs); assert_eq!( actual.unwrap().to_token_stream().to_string(), "initialization_method" ); - let actual = contains_use_discriminant(&item_struct); + let actual = contains_use_discriminant(&item_enum); assert!(actual.unwrap()); } #[test] fn test_init_function_with_use_discriminant_with_crate() { - let item_struct = syn::parse2::(quote! { + let item_enum: ItemEnum = parse_quote! { #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh(init = initialization_method, crate = "reexporter::borsh", use_discriminant=true)] enum A { @@ -391,18 +377,17 @@ mod tests { C, D, } - }) - .unwrap(); + }; - let actual = contains_initialize_with(&item_struct.attrs); + let actual = contains_initialize_with(&item_enum.attrs); assert_eq!( actual.unwrap().to_token_stream().to_string(), "initialization_method" ); - let actual = contains_use_discriminant(&item_struct); + let actual = contains_use_discriminant(&item_enum); assert!(actual.unwrap()); - let crate_ = get_crate(&item_struct.attrs); + let crate_ = get_crate(&item_enum.attrs); assert_eq!( crate_.unwrap().to_token_stream().to_string(), "reexporter :: borsh" diff --git a/borsh-derive/src/internals/attributes/mod.rs b/borsh-derive/src/internals/attributes/mod.rs index 4c5a69d4d..a069bc1ec 100644 --- a/borsh-derive/src/internals/attributes/mod.rs +++ b/borsh-derive/src/internals/attributes/mod.rs @@ -7,44 +7,100 @@ pub mod parsing; /// first field is attr name /// second field is its expected value format representation for error printing #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] -pub struct Symbol(pub &'static str, pub &'static str); +pub struct Symbol { + pub name: &'static str, + pub expected: &'static str, + support: AsyncSupport, +} + +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] +enum AsyncSupport { + Sync, + Async, + Both, +} + +impl Symbol { + pub const fn new(name: &'static str, expected: &'static str) -> Self { + Self { + name, + expected, + support: AsyncSupport::Both, + } + } + + pub const fn new_sync(name: &'static str, expected: &'static str) -> Self { + Self { + name, + expected, + support: AsyncSupport::Sync, + } + } + + pub const fn new_async(name: &'static str, expected: &'static str) -> Self { + Self { + name, + expected, + support: AsyncSupport::Async, + } + } + + pub const fn test_support(&self) -> bool { + if IS_ASYNC { + matches!(self.support, AsyncSupport::Async | AsyncSupport::Both) + } else { + matches!(self.support, AsyncSupport::Sync | AsyncSupport::Both) + } + } +} -/// borsh - top level prefix in nested meta attribute -pub const BORSH: Symbol = Symbol("borsh", "borsh(...)"); -/// bound - sub-borsh nested meta, field-level only, `BorshSerialize` and `BorshDeserialize` contexts -pub const BOUND: Symbol = Symbol("bound", "bound(...)"); -// use_discriminant - sub-borsh nested meta, item-level only, enums only, `BorshSerialize` and `BorshDeserialize` contexts -pub const USE_DISCRIMINANT: Symbol = Symbol("use_discriminant", "use_discriminant = ..."); -/// serialize - sub-bound nested meta attribute -pub const SERIALIZE: Symbol = Symbol("serialize", "serialize = ..."); -/// deserialize - sub-bound nested meta attribute -pub const DESERIALIZE: Symbol = Symbol("deserialize", "deserialize = ..."); -/// skip - sub-borsh nested meta, field-level only attribute, `BorshSerialize`, `BorshDeserialize`, `BorshSchema` contexts -pub const SKIP: Symbol = Symbol("skip", "skip"); -/// init - sub-borsh nested meta, item-level only attribute `BorshDeserialize` context -pub const INIT: Symbol = Symbol("init", "init = ..."); -/// serialize_with - sub-borsh nested meta, field-level only, `BorshSerialize` context -pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with", "serialize_with = ..."); -/// deserialize_with - sub-borsh nested meta, field-level only, `BorshDeserialize` context -pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with", "deserialize_with = ..."); -/// crate - sub-borsh nested meta, item-level only, `BorshSerialize`, `BorshDeserialize`, `BorshSchema` contexts -pub const CRATE: Symbol = Symbol("crate", "crate = ..."); +/// `borsh` - top level prefix in nested meta attribute +pub const BORSH: Symbol = Symbol::new("borsh", "borsh(...)"); +/// `bound` - sub-borsh nested meta, field-level only; `BorshSerialize` and `BorshDeserialize` contexts +pub const BOUND: Symbol = Symbol::new("bound", "bound(...)"); +/// `async_bound` - sub-borsh nested meta, field-level only; `BorshSerializeAsync` and `BorshDeserializeAsync` contexts +pub const ASYNC_BOUND: Symbol = Symbol::new_async("async_bound", "async_bound(...)"); +/// `use_discriminant` - sub-borsh nested meta, item-level only, enums only; +/// `BorshSerialize`, `BorshDeserialize`, `BorshSerializeAsync` and `BorshDeserializeAsync` contexts +pub const USE_DISCRIMINANT: Symbol = Symbol::new("use_discriminant", "use_discriminant = ..."); +/// `serialize` - sub-bound nested meta attribute +pub const SERIALIZE: Symbol = Symbol::new("serialize", "serialize = ..."); +/// `deserialize` - sub-bound nested meta attribute +pub const DESERIALIZE: Symbol = Symbol::new("deserialize", "deserialize = ..."); +/// `skip` - sub-borsh nested meta, field-level only attribute; +/// `BorshSerialize`, `BorshDeserialize`, `BorshSerializeAsync`, `BorshDeserializeAsync` and `BorshSchema` contexts +pub const SKIP: Symbol = Symbol::new("skip", "skip"); +/// `init` - sub-borsh nested meta, item-level only attribute; `BorshDeserialize` and `BorshDeserializeAsync` contexts +pub const INIT: Symbol = Symbol::new("init", "init = ..."); +/// `serialize_with` - sub-borsh nested meta, field-level only; `BorshSerialize` context +pub const SERIALIZE_WITH: Symbol = Symbol::new_sync("serialize_with", "serialize_with = ..."); +/// `deserialize_with` - sub-borsh nested meta, field-level only; `BorshDeserialize` context +pub const DESERIALIZE_WITH: Symbol = Symbol::new_sync("deserialize_with", "deserialize_with = ..."); +/// `serialize_with_async` - sub-borsh nested meta, field-level only; `BorshSerializeAsync` context +pub const SERIALIZE_WITH_ASYNC: Symbol = + Symbol::new_async("serialize_with_async", "serialize_with_async = ..."); +/// `deserialize_with_async` - sub-borsh nested meta, field-level only; `BorshDeserializeAsync` context +pub const DESERIALIZE_WITH_ASYNC: Symbol = + Symbol::new_async("deserialize_with_async", "deserialize_with_async = ..."); +/// `crate` - sub-borsh nested meta, item-level only; +/// `BorshSerialize`, `BorshDeserialize`, `BorshSerializeAsync`, `BorshDeserializeAsync` and `BorshSchema` contexts +pub const CRATE: Symbol = Symbol::new("crate", "crate = ..."); #[cfg(feature = "schema")] pub mod schema_keys { use super::Symbol; - /// schema - sub-borsh nested meta, `BorshSchema` context - pub const SCHEMA: Symbol = Symbol("schema", "schema(...)"); - /// params - sub-schema nested meta, field-level only attribute - pub const PARAMS: Symbol = Symbol("params", "params = ..."); - /// serialize_with - sub-borsh nested meta, field-level only, `BorshSerialize` context - /// with_funcs - sub-schema nested meta, field-level only attribute - pub const WITH_FUNCS: Symbol = Symbol("with_funcs", "with_funcs(...)"); - /// declaration - sub-with_funcs nested meta, field-level only attribute - pub const DECLARATION: Symbol = Symbol("declaration", "declaration = ..."); - /// definitions - sub-with_funcs nested meta, field-level only attribute - pub const DEFINITIONS: Symbol = Symbol("definitions", "definitions = ..."); + /// `schema` - sub-borsh nested meta, `BorshSchema` context + pub const SCHEMA: Symbol = Symbol::new("schema", "schema(...)"); + /// `params` - sub-schema nested meta, field-level only attribute + pub const PARAMS: Symbol = Symbol::new("params", "params = ..."); + /// `serialize_with` - sub-borsh nested meta, field-level only, `BorshSerialize` context + /// `with_funcs` - sub-schema nested meta, field-level only attribute + pub const WITH_FUNCS: Symbol = Symbol::new("with_funcs", "with_funcs(...)"); + /// `declaration` - sub-with_funcs nested meta, field-level only attribute + pub const DECLARATION: Symbol = Symbol::new("declaration", "declaration = ..."); + /// `definitions` - sub-with_funcs nested meta, field-level only attribute + pub const DEFINITIONS: Symbol = Symbol::new("definitions", "definitions = ..."); } #[derive(Clone, Copy)] @@ -54,23 +110,23 @@ pub enum BoundType { } impl PartialEq for Path { fn eq(&self, word: &Symbol) -> bool { - self.is_ident(word.0) + self.is_ident(word.name) } } impl<'a> PartialEq for &'a Path { fn eq(&self, word: &Symbol) -> bool { - self.is_ident(word.0) + self.is_ident(word.name) } } fn get_one_attribute(attrs: &[Attribute]) -> syn::Result> { - let count = attrs.iter().filter(|attr| attr.path() == BORSH).count(); - let borsh = attrs.iter().find(|attr| attr.path() == BORSH); - if count > 1 { + let mut attrs = attrs.iter().filter(|attr| attr.path() == BORSH); + let borsh = attrs.next(); + if let Some(other_borsh) = attrs.next() { return Err(syn::Error::new_spanned( - borsh.unwrap(), - format!("multiple `{}` attributes not allowed", BORSH.0), + other_borsh, + format!("multiple `{}` attributes not allowed", BORSH.name), )); } Ok(borsh) diff --git a/borsh-derive/src/internals/attributes/parsing.rs b/borsh-derive/src/internals/attributes/parsing.rs index 7ebf8e778..4eebee807 100644 --- a/borsh-derive/src/internals/attributes/parsing.rs +++ b/borsh-derive/src/internals/attributes/parsing.rs @@ -27,7 +27,7 @@ fn get_lit_str2( expr, format!( "expected borsh {} attribute to be a string: `{} = \"...\"`", - attr_name.0, meta_item_name.0 + attr_name.name, meta_item_name.name ), )) } @@ -77,11 +77,11 @@ where } } if !match_ { - let keys_strs = map.keys().map(|symbol| symbol.1).collect::>(); + let keys_strs = map.keys().map(|symbol| symbol.expected).collect::>(); let keys_strs = keys_strs.join(", "); return Err(meta.error(format_args!( "malformed {0} attribute, expected `{0}({1})`", - attr_name.0, keys_strs + attr_name.name, keys_strs ))); } Ok(()) diff --git a/borsh-derive/src/internals/deserialize/enums/mod.rs b/borsh-derive/src/internals/deserialize/enums/mod.rs index fb405e90d..925d73301 100644 --- a/borsh-derive/src/internals/deserialize/enums/mod.rs +++ b/borsh-derive/src/internals/deserialize/enums/mod.rs @@ -1,65 +1,87 @@ -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{Fields, ItemEnum, Path, Variant}; +use syn::{Fields, ItemEnum, Path, Token, Variant}; use crate::internals::{attributes::item, deserialize, enum_discriminant::Discriminants, generics}; -pub fn process(input: &ItemEnum, cratename: Path) -> syn::Result { +pub fn process( + input: ItemEnum, + cratename: Path, +) -> syn::Result { let name = &input.ident; - let generics = generics::without_defaults(&input.generics); + let use_discriminant = item::contains_use_discriminant(&input)?; + let generics = generics::without_defaults(input.generics); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let mut where_clause = generics::default_where(where_clause); let mut variant_arms = TokenStream2::new(); - let use_discriminant = item::contains_use_discriminant(input)?; let discriminants = Discriminants::new(&input.variants); let mut generics_output = deserialize::GenericsOutput::new(&generics); - for (variant_idx, variant) in input.variants.iter().enumerate() { - let variant_body = process_variant(variant, &cratename, &mut generics_output)?; - let variant_ident = &variant.ident; + for (variant_idx, variant) in input.variants.into_iter().enumerate() { + let variant_body = process_variant::(&variant, &cratename, &mut generics_output)?; + let variant_ident = variant.ident; + + let discriminant_value = + discriminants.get(&variant_ident, use_discriminant, variant_idx)?; - let discriminant_value = discriminants.get(variant_ident, use_discriminant, variant_idx)?; + // `if` branches are used instead of `match` branches, because `discriminant_value` might be a function call variant_arms.extend(quote! { if variant_tag == #discriminant_value { #name::#variant_ident #variant_body } else }); } - let init = if let Some(method_ident) = item::contains_initialize_with(&input.attrs)? { - quote! { - return_value.#method_ident(); - } + let init = item::contains_initialize_with(&input.attrs)? + .map(|method_ident| quote! { return_value.#method_ident(); }); + let r#mut = init.is_some().then(|| Token![mut](Span::call_site())); + generics_output.extend::(&mut where_clause, &cratename); + + let deserialize_trait = Ident::new( + if IS_ASYNC { + "BorshDeserializeAsync" + } else { + "BorshDeserialize" + }, + Span::call_site(), + ); + let enum_ext = Ident::new( + if IS_ASYNC { "EnumExtAsync" } else { "EnumExt" }, + Span::call_site(), + ); + let read_trait_path = if IS_ASYNC { + quote! { async_io::AsyncRead } } else { - quote! {} + quote! { io::Read } }; - generics_output.extend(&mut where_clause, &cratename); + let r#async = IS_ASYNC.then(|| Token![async](Span::call_site())); + let dot_await = IS_ASYNC.then(|| quote! { .await }); Ok(quote! { - impl #impl_generics #cratename::de::BorshDeserialize for #name #ty_generics #where_clause { - fn deserialize_reader<__R: #cratename::io::Read>(reader: &mut __R) -> ::core::result::Result { - let tag = ::deserialize_reader(reader)?; - ::deserialize_variant(reader, tag) + impl #impl_generics #cratename::de::#deserialize_trait for #name #ty_generics #where_clause { + #r#async fn deserialize_reader<__R: #cratename::#read_trait_path>(reader: &mut __R) -> ::core::result::Result { + let tag = ::deserialize_reader(reader)#dot_await?; + ::deserialize_variant(reader, tag)#dot_await } } - impl #impl_generics #cratename::de::EnumExt for #name #ty_generics #where_clause { - fn deserialize_variant<__R: #cratename::io::Read>( + impl #impl_generics #cratename::de::#enum_ext for #name #ty_generics #where_clause { + #r#async fn deserialize_variant<__R: #cratename::#read_trait_path>( reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = + let #r#mut return_value = #variant_arms { - return Err(#cratename::io::Error::new( + return ::core::result::Result::Err(#cratename::io::Error::new( #cratename::io::ErrorKind::InvalidData, #cratename::__private::maybestd::format!("Unexpected variant tag: {:?}", variant_tag), )) }; #init - Ok(return_value) + ::core::result::Result::Ok(return_value) } } }) } -fn process_variant( +fn process_variant( variant: &Variant, cratename: &Path, generics: &mut deserialize::GenericsOutput, @@ -68,13 +90,13 @@ fn process_variant( match &variant.fields { Fields::Named(fields) => { for field in &fields.named { - deserialize::process_field(field, cratename, &mut body, generics)?; + deserialize::process_field::(field, cratename, &mut body, generics)?; } body = quote! { { #body }}; } Fields::Unnamed(fields) => { for field in fields.unnamed.iter() { - deserialize::process_field(field, cratename, &mut body, generics)?; + deserialize::process_field::(field, cratename, &mut body, generics)?; } body = quote! { ( #body )}; } @@ -85,15 +107,16 @@ fn process_variant( #[cfg(test)] mod tests { + use syn::parse_quote; + + use super::*; use crate::internals::test_helpers::{ default_cratename, local_insta_assert_snapshot, pretty_print_syn_str, }; - use super::*; - #[test] fn borsh_skip_struct_variant_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AA { B { #[borsh(skip)] @@ -104,16 +127,18 @@ mod tests { beta: u8, } } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_skip_tuple_variant_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AAT { B(#[borsh(skip)] i32, u32), @@ -121,16 +146,18 @@ mod tests { beta: u8, } } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_enum_with_custom_crate() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { B { x: HashMap, @@ -138,17 +165,20 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; + + let crate_: Path = parse_quote! { reexporter::borsh }; + + let actual = process::(item_enum.clone(), crate_.clone()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let crate_: Path = syn::parse2(quote! { reexporter::borsh }).unwrap(); - let actual = process(&item_struct, crate_).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_generics() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { B { x: HashMap, @@ -156,16 +186,18 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn bound_generics() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { x: HashMap, @@ -173,16 +205,18 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn recursive_enum() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { x: HashMap, @@ -190,16 +224,17 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_borsh_skip_struct_field() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { #[borsh(skip)] @@ -208,17 +243,18 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_borsh_skip_tuple_field() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { x: HashMap, @@ -226,17 +262,18 @@ mod tests { }, C(K, #[borsh(skip)] Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_deserialize_bound() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { C { a: String, @@ -248,17 +285,41 @@ mod tests { }, D(u32, u32), } - }) - .unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn generic_deserialize_async_bound() { + let item_enum: ItemEnum = parse_quote! { + enum A { + C { + a: String, + #[borsh(async_bound(deserialize = + "T: PartialOrd + Hash + Eq + borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync" + ))] + b: HashMap, + }, + D(u32, u32), + } + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn check_deserialize_with_attr() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum C { C3(u64, u64), C4 { @@ -267,17 +328,38 @@ mod tests { y: ThirdParty }, } - }) - .unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn check_deserialize_with_async_attr() { + let item_enum: ItemEnum = parse_quote! { + enum C { + C3(u64, u64), + C4 { + x: u64, + #[borsh(deserialize_with_async = "third_party_impl::deserialize_third_party")] + y: ThirdParty + }, + } + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_discriminant_false() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(use_discriminant = false)] enum X { A, @@ -287,15 +369,18 @@ mod tests { E = 10, F, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } + #[test] fn borsh_discriminant_true() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(use_discriminant = true)] enum X { A, @@ -305,15 +390,18 @@ mod tests { E = 10, F, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } + #[test] fn borsh_init_func() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(init = initialization_method)] enum A { A, @@ -323,9 +411,12 @@ mod tests { E, F, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false-2.snap new file mode 100644 index 000000000..2d8c2ec53 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false-2.snap @@ -0,0 +1,43 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for X { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for X { + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + X::A + } else if variant_tag == 1u8 { + X::B + } else if variant_tag == 2u8 { + X::C + } else if variant_tag == 3u8 { + X::D + } else if variant_tag == 4u8 { + X::E + } else if variant_tag == 5u8 { + X::F + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false.snap index 1e0446681..14c718d83 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for X { fn deserialize_reader<__R: borsh::io::Read>( @@ -15,7 +15,7 @@ impl borsh::de::EnumExt for X { reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { X::A } else if variant_tag == 1u8 { X::B @@ -28,7 +28,7 @@ impl borsh::de::EnumExt for X { } else if variant_tag == 5u8 { X::F } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -37,6 +37,6 @@ impl borsh::de::EnumExt for X { ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true-2.snap new file mode 100644 index 000000000..5a617705e --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true-2.snap @@ -0,0 +1,43 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for X { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for X { + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0 { + X::A + } else if variant_tag == 20 { + X::B + } else if variant_tag == 20 + 1 { + X::C + } else if variant_tag == 20 + 1 + 1 { + X::D + } else if variant_tag == 10 { + X::E + } else if variant_tag == 10 + 1 { + X::F + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true.snap index add0f62ed..65e363b07 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for X { fn deserialize_reader<__R: borsh::io::Read>( @@ -15,7 +15,7 @@ impl borsh::de::EnumExt for X { reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0 { + let return_value = if variant_tag == 0 { X::A } else if variant_tag == 20 { X::B @@ -28,7 +28,7 @@ impl borsh::de::EnumExt for X { } else if variant_tag == 10 + 1 { X::F } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -37,6 +37,6 @@ impl borsh::de::EnumExt for X { ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func-2.snap new file mode 100644 index 000000000..dec3fd255 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func-2.snap @@ -0,0 +1,44 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A { + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let mut return_value = if variant_tag == 0u8 { + A::A + } else if variant_tag == 1u8 { + A::B + } else if variant_tag == 2u8 { + A::C + } else if variant_tag == 3u8 { + A::D + } else if variant_tag == 4u8 { + A::E + } else if variant_tag == 5u8 { + A::F + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + return_value.initialization_method(); + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func.snap index 28dd7dbce..54a14823e 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A { fn deserialize_reader<__R: borsh::io::Read>( @@ -28,7 +28,7 @@ impl borsh::de::EnumExt for A { } else if variant_tag == 5u8 { A::F } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -38,6 +38,6 @@ impl borsh::de::EnumExt for A { ) }; return_value.initialization_method(); - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap new file mode 100644 index 000000000..b95070208 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap @@ -0,0 +1,42 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for AA { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for AA { + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + AA::B { + c: ::core::default::Default::default(), + d: ::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + AA::NegatedVariant { + beta: ::deserialize_reader(reader) + .await?, + } + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap index a8a2d9e1a..5938210dc 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for AA { fn deserialize_reader<__R: borsh::io::Read>( @@ -15,17 +15,17 @@ impl borsh::de::EnumExt for AA { reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { AA::B { - c: core::default::Default::default(), - d: borsh::BorshDeserialize::deserialize_reader(reader)?, + c: ::core::default::Default::default(), + d: ::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { AA::NegatedVariant { - beta: borsh::BorshDeserialize::deserialize_reader(reader)?, + beta: ::deserialize_reader(reader)?, } } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -34,6 +34,6 @@ impl borsh::de::EnumExt for AA { ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap new file mode 100644 index 000000000..51758af91 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap @@ -0,0 +1,41 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for AAT { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for AAT { + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + AAT::B( + ::core::default::Default::default(), + ::deserialize_reader(reader).await?, + ) + } else if variant_tag == 1u8 { + AAT::NegatedVariant { + beta: ::deserialize_reader(reader) + .await?, + } + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap index 60149fc60..7303215f7 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for AAT { fn deserialize_reader<__R: borsh::io::Read>( @@ -15,17 +15,17 @@ impl borsh::de::EnumExt for AAT { reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { AAT::B( - core::default::Default::default(), - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::default::Default::default(), + ::deserialize_reader(reader)?, ) } else if variant_tag == 1u8 { AAT::NegatedVariant { - beta: borsh::BorshDeserialize::deserialize_reader(reader)?, + beta: ::deserialize_reader(reader)?, } } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -34,6 +34,6 @@ impl borsh::de::EnumExt for AAT { ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics-2.snap new file mode 100644 index 000000000..1b3648e82 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics-2.snap @@ -0,0 +1,59 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::B { + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::C( + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics.snap index 6b31f4bc6..abae695c1 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where @@ -27,18 +27,21 @@ where reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::B { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + x: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserialize::deserialize_reader(reader)?, - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + as borsh::BorshDeserialize>::deserialize_reader(reader)?, ) } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -47,6 +50,6 @@ where ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr-2.snap new file mode 100644 index 000000000..6ae29e32e --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr-2.snap @@ -0,0 +1,50 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for C +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for C +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + C::C3( + ::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + ) + } else if variant_tag == 1u8 { + C::C4 { + x: ::deserialize_reader(reader) + .await?, + y: third_party_impl::deserialize_third_party(reader).await?, + } + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr.snap new file mode 100644 index 000000000..63c7c21d3 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr.snap @@ -0,0 +1,51 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserialize for C +where + K: borsh::de::BorshDeserialize, + V: borsh::de::BorshDeserialize, +{ + fn deserialize_reader<__R: borsh::io::Read>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader)?; + ::deserialize_variant(reader, tag) + } +} +impl borsh::de::EnumExt for C +where + K: borsh::de::BorshDeserialize, + V: borsh::de::BorshDeserialize, +{ + fn deserialize_variant<__R: borsh::io::Read>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + C::C3( + ::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + ) + } else if variant_tag == 1u8 { + C::C4 { + x: ::deserialize_reader(reader)?, + y: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + } + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr-2.snap new file mode 100644 index 000000000..4be6ba10b --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr-2.snap @@ -0,0 +1,54 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for C +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for C +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + C::C3( + ::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + ) + } else if variant_tag == 1u8 { + C::C4 { + x: ::deserialize_reader(reader) + .await?, + y: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + } + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr.snap index 968e0c3b5..fe50c66c2 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for C where @@ -23,18 +23,18 @@ where reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { C::C3( - borsh::BorshDeserialize::deserialize_reader(reader)?, - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, ) } else if variant_tag == 1u8 { C::C4 { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, + x: ::deserialize_reader(reader)?, y: third_party_impl::deserialize_third_party(reader)?, } } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -43,6 +43,6 @@ where ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap new file mode 100644 index 000000000..4329633ca --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap @@ -0,0 +1,57 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, + K: ::core::default::Default, + V: ::core::default::Default, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, + K: ::core::default::Default, + V: ::core::default::Default, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::B { + x: ::core::default::Default::default(), + y: ::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::C( + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field.snap index cde62e488..5c6546e30 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field.snap @@ -1,14 +1,14 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where V: Value, K: borsh::de::BorshDeserialize, U: borsh::de::BorshDeserialize, - K: core::default::Default, - V: core::default::Default, + K: ::core::default::Default, + V: ::core::default::Default, { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, @@ -22,25 +22,25 @@ where V: Value, K: borsh::de::BorshDeserialize, U: borsh::de::BorshDeserialize, - K: core::default::Default, - V: core::default::Default, + K: ::core::default::Default, + V: ::core::default::Default, { fn deserialize_variant<__R: borsh::io::Read>( reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::B { - x: core::default::Default::default(), - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + x: ::core::default::Default::default(), + y: ::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserialize::deserialize_reader(reader)?, - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + as borsh::BorshDeserialize>::deserialize_reader(reader)?, ) } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -49,6 +49,6 @@ where ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap new file mode 100644 index 000000000..0910625cb --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap @@ -0,0 +1,58 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, + U: ::core::default::Default, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, + U: ::core::default::Default, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::B { + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::C( + ::deserialize_reader(reader).await?, + ::core::default::Default::default(), + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field.snap index 0cc108681..d4087a395 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field.snap @@ -1,13 +1,13 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where V: Value, K: borsh::de::BorshDeserialize, V: borsh::de::BorshDeserialize, - U: core::default::Default, + U: ::core::default::Default, { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, @@ -21,24 +21,27 @@ where V: Value, K: borsh::de::BorshDeserialize, V: borsh::de::BorshDeserialize, - U: core::default::Default, + U: ::core::default::Default, { fn deserialize_variant<__R: borsh::io::Read>( reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::B { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + x: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserialize::deserialize_reader(reader)?, - core::default::Default::default(), + ::deserialize_reader(reader)?, + ::core::default::Default::default(), ) } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -47,6 +50,6 @@ where ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound-2.snap new file mode 100644 index 000000000..0635c01ac --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound-2.snap @@ -0,0 +1,54 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + T: PartialOrd + Hash + Eq + borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A +where + T: PartialOrd + Hash + Eq + borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::C { + a: ::deserialize_reader(reader) + .await?, + b: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::D( + ::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound.snap new file mode 100644 index 000000000..7463da4e0 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound.snap @@ -0,0 +1,51 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserialize for A +where + T: borsh::de::BorshDeserialize, + U: borsh::de::BorshDeserialize, +{ + fn deserialize_reader<__R: borsh::io::Read>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader)?; + ::deserialize_variant(reader, tag) + } +} +impl borsh::de::EnumExt for A +where + T: borsh::de::BorshDeserialize, + U: borsh::de::BorshDeserialize, +{ + fn deserialize_variant<__R: borsh::io::Read>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::C { + a: ::deserialize_reader(reader)?, + b: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + } + } else if variant_tag == 1u8 { + A::D( + ::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound-2.snap new file mode 100644 index 000000000..0eedb6981 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound-2.snap @@ -0,0 +1,54 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + T: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A +where + T: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::C { + a: ::deserialize_reader(reader) + .await?, + b: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::D( + ::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap index adf641118..75ac1987e 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where @@ -23,18 +23,21 @@ where reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::C { - a: borsh::BorshDeserialize::deserialize_reader(reader)?, - b: borsh::BorshDeserialize::deserialize_reader(reader)?, + a: ::deserialize_reader(reader)?, + b: as borsh::BorshDeserialize>::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { A::D( - borsh::BorshDeserialize::deserialize_reader(reader)?, - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, ) } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -43,6 +46,6 @@ where ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum-2.snap new file mode 100644 index 000000000..705858356 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum-2.snap @@ -0,0 +1,57 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::B { + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::C( + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum.snap index b3c8f7790..852382274 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where @@ -25,18 +25,21 @@ where reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::B { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + x: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserialize::deserialize_reader(reader)?, - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + as borsh::BorshDeserialize>::deserialize_reader(reader)?, ) } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -45,6 +48,6 @@ where ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate-2.snap new file mode 100644 index 000000000..a6eb2c787 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate-2.snap @@ -0,0 +1,61 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl reexporter::borsh::de::BorshDeserializeAsync for A { + async fn deserialize_reader<__R: reexporter::borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader( + reader, + ) + .await?; + ::deserialize_variant(reader, tag) + .await + } +} +impl reexporter::borsh::de::EnumExtAsync for A { + async fn deserialize_variant<__R: reexporter::borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::B { + x: as reexporter::borsh::BorshDeserializeAsync>::deserialize_reader( + reader, + ) + .await?, + y: ::deserialize_reader( + reader, + ) + .await?, + } + } else if variant_tag == 1u8 { + A::C( + ::deserialize_reader( + reader, + ) + .await?, + as reexporter::borsh::BorshDeserializeAsync>::deserialize_reader( + reader, + ) + .await?, + ) + } else { + return ::core::result::Result::Err( + reexporter::borsh::io::Error::new( + reexporter::borsh::io::ErrorKind::InvalidData, + reexporter::borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate.snap index 88457ee99..16400f884 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl reexporter::borsh::de::BorshDeserialize for A { fn deserialize_reader<__R: reexporter::borsh::io::Read>( @@ -17,18 +17,25 @@ impl reexporter::borsh::de::EnumExt for A { reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::B { - x: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, - y: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, + x: as reexporter::borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader( + reader, + )?, } } else if variant_tag == 1u8 { A::C( - reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, - reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + as reexporter::borsh::BorshDeserialize>::deserialize_reader(reader)?, ) } else { - return Err( + return ::core::result::Result::Err( reexporter::borsh::io::Error::new( reexporter::borsh::io::ErrorKind::InvalidData, reexporter::borsh::__private::maybestd::format!( @@ -37,6 +44,6 @@ impl reexporter::borsh::de::EnumExt for A { ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics-2.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics-2.snap new file mode 100644 index 000000000..e39c1335d --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics-2.snap @@ -0,0 +1,57 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let tag = ::deserialize_reader(reader) + .await?; + ::deserialize_variant(reader, tag).await + } +} +impl borsh::de::EnumExtAsync for A +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + variant_tag: u8, + ) -> ::core::result::Result { + let return_value = if variant_tag == 0u8 { + A::B { + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::C( + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + ) + } else { + return ::core::result::Result::Err( + borsh::io::Error::new( + borsh::io::ErrorKind::InvalidData, + borsh::__private::maybestd::format!( + "Unexpected variant tag: {:?}", variant_tag + ), + ), + ) + }; + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics.snap index d8b85259c..ef9765ea6 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where @@ -25,18 +25,21 @@ where reader: &mut __R, variant_tag: u8, ) -> ::core::result::Result { - let mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::B { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + x: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserialize::deserialize_reader(reader)?, - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + as borsh::BorshDeserialize>::deserialize_reader(reader)?, ) } else { - return Err( + return ::core::result::Result::Err( borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, borsh::__private::maybestd::format!( @@ -45,6 +48,6 @@ where ), ) }; - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/mod.rs b/borsh-derive/src/internals/deserialize/mod.rs index f9732c05f..166841979 100644 --- a/borsh-derive/src/internals/deserialize/mod.rs +++ b/borsh-derive/src/internals/deserialize/mod.rs @@ -1,6 +1,6 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use syn::{ExprPath, Generics, Ident, Path}; +use syn::{parse_quote, ExprPath, Generics, Ident, Path, Type}; use super::{ attributes::{field, BoundType}, @@ -25,9 +25,14 @@ impl GenericsOutput { default_visitor: generics::FindTyParams::new(generics), } } - fn extend(self, where_clause: &mut syn::WhereClause, cratename: &Path) { - let de_trait: Path = syn::parse2(quote! { #cratename::de::BorshDeserialize }).unwrap(); - let default_trait: Path = syn::parse2(quote! { core::default::Default }).unwrap(); + + fn extend(self, where_clause: &mut syn::WhereClause, cratename: &Path) { + let de_trait: Path = if IS_ASYNC { + parse_quote! { #cratename::de::BorshDeserializeAsync } + } else { + parse_quote! { #cratename::de::BorshDeserialize } + }; + let default_trait: Path = parse_quote! { ::core::default::Default }; let de_predicates = generics::compute_predicates(self.deserialize_visitor.process_for_bounds(), &de_trait); let default_predicates = @@ -38,7 +43,7 @@ impl GenericsOutput { } } -fn process_field( +fn process_field( field: &syn::Field, cratename: &Path, body: &mut TokenStream2, @@ -46,10 +51,16 @@ fn process_field( ) -> syn::Result<()> { let parsed = field::Attributes::parse(&field.attrs)?; - generics - .overrides - .extend(parsed.collect_bounds(BoundType::Deserialize)); - let needs_bounds_derive = parsed.needs_bounds_derive(BoundType::Deserialize); + generics.overrides.extend(if IS_ASYNC { + parsed.collect_async_bounds(BoundType::Deserialize) + } else { + parsed.collect_bounds(BoundType::Deserialize) + }); + let needs_bounds_derive = if IS_ASYNC { + parsed.needs_async_bounds_derive(BoundType::Deserialize) + } else { + parsed.needs_bounds_derive(BoundType::Deserialize) + }; let field_name = field.ident.as_ref(); let delta = if parsed.skip { @@ -61,7 +72,16 @@ fn process_field( if needs_bounds_derive { generics.deserialize_visitor.visit_field(field); } - field_output(field_name, cratename, parsed.deserialize_with) + field_output::( + field_name, + &field.ty, + cratename, + if IS_ASYNC { + parsed.deserialize_with_async + } else { + parsed.deserialize_with + }, + ) }; body.extend(delta); Ok(()) @@ -69,22 +89,31 @@ fn process_field( /// function which computes derive output [proc_macro2::TokenStream] /// of code, which deserializes single field -fn field_output( +fn field_output( field_name: Option<&Ident>, + field_type: &Type, cratename: &Path, deserialize_with: Option, ) -> TokenStream2 { - let default_path: ExprPath = - syn::parse2(quote! { #cratename::BorshDeserialize::deserialize_reader }).unwrap(); - let path: ExprPath = deserialize_with.unwrap_or(default_path); + let default_path = || { + let deserialize_trait = Ident::new( + if IS_ASYNC { + "BorshDeserializeAsync" + } else { + "BorshDeserialize" + }, + proc_macro2::Span::call_site(), + ); + parse_quote! { <#field_type as #cratename::#deserialize_trait>::deserialize_reader } + }; + + let path: ExprPath = deserialize_with.unwrap_or_else(default_path); + let dot_await = IS_ASYNC.then(|| quote! { .await }); + if let Some(field_name) = field_name { - quote! { - #field_name: #path(reader)?, - } + quote! { #field_name: #path(reader)#dot_await?, } } else { - quote! { - #path(reader)?, - } + quote! { #path(reader)#dot_await?, } } } @@ -92,10 +121,8 @@ fn field_output( /// of code, which deserializes single skipped field fn field_default_output(field_name: Option<&Ident>) -> TokenStream2 { if let Some(field_name) = field_name { - quote! { - #field_name: core::default::Default::default(), - } + quote! { #field_name: ::core::default::Default::default(), } } else { - quote! { core::default::Default::default(), } + quote! { ::core::default::Default::default(), } } } diff --git a/borsh-derive/src/internals/deserialize/structs/mod.rs b/borsh-derive/src/internals/deserialize/structs/mod.rs index 0faaec309..759628f76 100644 --- a/borsh-derive/src/internals/deserialize/structs/mod.rs +++ b/borsh-derive/src/internals/deserialize/structs/mod.rs @@ -1,12 +1,15 @@ -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{Fields, ItemStruct, Path}; +use syn::{Fields, ItemStruct, Path, Token}; use crate::internals::{attributes::item, deserialize, generics}; -pub fn process(input: &ItemStruct, cratename: Path) -> syn::Result { +pub fn process( + input: ItemStruct, + cratename: Path, +) -> syn::Result { let name = &input.ident; - let generics = generics::without_defaults(&input.generics); + let generics = generics::without_defaults(input.generics); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let mut where_clause = generics::default_where(where_clause); let mut body = TokenStream2::new(); @@ -15,193 +18,222 @@ pub fn process(input: &ItemStruct, cratename: Path) -> syn::Result let return_value = match &input.fields { Fields::Named(fields) => { for field in &fields.named { - deserialize::process_field(field, &cratename, &mut body, &mut generics_output)?; - } - quote! { - Self { #body } + deserialize::process_field::( + field, + &cratename, + &mut body, + &mut generics_output, + )?; } + quote! { Self { #body } } } Fields::Unnamed(fields) => { for field in fields.unnamed.iter() { - deserialize::process_field(field, &cratename, &mut body, &mut generics_output)?; - } - quote! { - Self( #body ) - } - } - Fields::Unit => { - quote! { - Self {} + deserialize::process_field::( + field, + &cratename, + &mut body, + &mut generics_output, + )?; } + quote! { Self( #body ) } } + Fields::Unit => quote! { Self {} }, }; - generics_output.extend(&mut where_clause, &cratename); - - if let Some(method_ident) = item::contains_initialize_with(&input.attrs)? { - Ok(quote! { - impl #impl_generics #cratename::de::BorshDeserialize for #name #ty_generics #where_clause { - fn deserialize_reader<__R: #cratename::io::Read>(reader: &mut __R) -> ::core::result::Result { - let mut return_value = #return_value; - return_value.#method_ident(); - Ok(return_value) - } - } - }) + generics_output.extend::(&mut where_clause, &cratename); + + let deserialize_trait = Ident::new( + if IS_ASYNC { + "BorshDeserializeAsync" + } else { + "BorshDeserialize" + }, + Span::call_site(), + ); + let read_trait_path = if IS_ASYNC { + quote! { async_io::AsyncRead } } else { - Ok(quote! { - impl #impl_generics #cratename::de::BorshDeserialize for #name #ty_generics #where_clause { - fn deserialize_reader<__R: #cratename::io::Read>(reader: &mut __R) -> ::core::result::Result { - Ok(#return_value) - } + quote! { io::Read } + }; + let r#async = IS_ASYNC.then(|| Token![async](Span::call_site())); + + let body = if let Some(method_ident) = item::contains_initialize_with(&input.attrs)? { + quote! { + let mut return_value = #return_value; + return_value.#method_ident(); + ::core::result::Result::Ok(return_value) + } + } else { + quote! { ::core::result::Result::Ok(#return_value) } + }; + + Ok(quote! { + impl #impl_generics #cratename::de::#deserialize_trait for #name #ty_generics #where_clause { + #r#async fn deserialize_reader<__R: #cratename::#read_trait_path>(reader: &mut __R) -> ::core::result::Result { + #body } - }) - } + } + }) } #[cfg(test)] mod tests { + use syn::parse_quote; + + use super::*; use crate::internals::test_helpers::{ default_cratename, local_insta_assert_snapshot, pretty_print_syn_str, }; - use super::*; - #[test] fn simple_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: u64, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_struct_with_custom_crate() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: u64, y: String, } - }) - .unwrap(); + }; - let crate_: Path = syn::parse2(quote! { reexporter::borsh }).unwrap(); - let actual = process(&item_struct, crate_).unwrap(); + let crate_: Path = parse_quote! { reexporter::borsh }; - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct.clone(), crate_.clone()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_generics() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: HashMap, y: String, } - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_generic_tuple_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct TupleA(T, u32); - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn bound_generics() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A where V: Value { x: HashMap, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn recursive_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct CRecC { a: String, b: HashMap, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip1() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G ( #[borsh(skip)] HashMap, U, ); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G ( HashMap, #[borsh(skip)] U, ); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_named_fields_struct_borsh_skip() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G { #[borsh(skip)] x: HashMap, y: U, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_deserialize_bound() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct C { a: String, #[borsh(bound(deserialize = @@ -210,56 +242,117 @@ mod tests { ))] b: HashMap, } - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn generic_deserialize_async_bound() { + let item_struct: ItemStruct = parse_quote! { + struct C { + a: String, + #[borsh(async_bound(deserialize = + "T: PartialOrd + Hash + Eq + borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync" + ))] + b: HashMap, + } + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn test_override_automatically_added_default_trait() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G1( #[borsh(skip,bound(deserialize = ""))] HashMap, U ); - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn test_override_automatically_added_default_trait_async() { + let item_struct: ItemStruct = parse_quote! { + struct G1( + #[borsh(skip,async_bound(deserialize = ""))] + HashMap, + U + ); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn check_deserialize_with_attr() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(deserialize_with = "third_party_impl::deserialize_third_party")] x: ThirdParty, y: u64, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } + + #[test] + fn check_deserialize_with_async_attr() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(deserialize_with_async = "third_party_impl::deserialize_third_party")] + x: ThirdParty, + y: u64, + } + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + #[test] fn borsh_init_func() { - let item_enum: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { #[borsh(init=initialization_method)] struct A { x: u64, y: String, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func-2.snap new file mode 100644 index 000000000..5c52c0507 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func-2.snap @@ -0,0 +1,17 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + let mut return_value = Self { + x: ::deserialize_reader(reader).await?, + y: ::deserialize_reader(reader) + .await?, + }; + return_value.initialization_method(); + ::core::result::Result::Ok(return_value) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func.snap index 61f51e48e..e449e90f7 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func.snap @@ -1,16 +1,16 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { let mut return_value = Self { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + x: ::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, }; return_value.initialization_method(); - Ok(return_value) + ::core::result::Result::Ok(return_value) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics-2.snap new file mode 100644 index 000000000..ef7898f88 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics-2.snap @@ -0,0 +1,24 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + V: Value, + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics.snap index dc4514d64..81363ce72 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where @@ -11,9 +11,9 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::result::Result::Ok(Self { + x: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, }) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr-2.snap new file mode 100644 index 000000000..a4a594f06 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr-2.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: third_party_impl::deserialize_third_party(reader).await?, + y: ::deserialize_reader(reader).await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr.snap new file mode 100644 index 000000000..7d0159738 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr.snap @@ -0,0 +1,21 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserialize for A +where + K: borsh::de::BorshDeserialize, + V: borsh::de::BorshDeserialize, +{ + fn deserialize_reader<__R: borsh::io::Read>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr-2.snap new file mode 100644 index 000000000..f9f1899de --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr-2.snap @@ -0,0 +1,22 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader).await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr.snap index 79a844803..8eb7e2997 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where @@ -10,9 +10,9 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { + ::core::result::Result::Ok(Self { x: third_party_impl::deserialize_third_party(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, }) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound-2.snap new file mode 100644 index 000000000..48f831c7c --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound-2.snap @@ -0,0 +1,23 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for C +where + T: PartialOrd + Hash + Eq + borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + a: ::deserialize_reader(reader) + .await?, + b: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound.snap new file mode 100644 index 000000000..634f837ce --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserialize for C +where + T: borsh::de::BorshDeserialize, + U: borsh::de::BorshDeserialize, +{ + fn deserialize_reader<__R: borsh::io::Read>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + a: ::deserialize_reader(reader)?, + b: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound-2.snap new file mode 100644 index 000000000..808a8ee96 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound-2.snap @@ -0,0 +1,23 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for C +where + T: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + a: ::deserialize_reader(reader) + .await?, + b: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound.snap index 7e4a0317b..0eaeeed68 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for C where @@ -10,9 +10,9 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { - a: borsh::BorshDeserialize::deserialize_reader(reader)?, - b: borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::result::Result::Ok(Self { + a: ::deserialize_reader(reader)?, + b: as borsh::BorshDeserialize>::deserialize_reader(reader)?, }) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap new file mode 100644 index 000000000..aece060e2 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap @@ -0,0 +1,19 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for G +where + U: borsh::de::BorshDeserializeAsync, + K: ::core::default::Default, + V: ::core::default::Default, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: ::core::default::Default::default(), + y: ::deserialize_reader(reader).await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap index c094081c6..380e5b217 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap @@ -1,19 +1,19 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for G where U: borsh::de::BorshDeserialize, - K: core::default::Default, - V: core::default::Default, + K: ::core::default::Default, + V: ::core::default::Default, { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { - x: core::default::Default::default(), - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::result::Result::Ok(Self { + x: ::core::default::Default::default(), + y: ::deserialize_reader(reader)?, }) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap new file mode 100644 index 000000000..e3b9f09c3 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap @@ -0,0 +1,21 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for G +where + U: borsh::de::BorshDeserializeAsync, + K: ::core::default::Default, + V: ::core::default::Default, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + Self( + ::core::default::Default::default(), + ::deserialize_reader(reader).await?, + ), + ) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap index 492cc2b14..a9a2aec29 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap @@ -1,20 +1,20 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for G where U: borsh::de::BorshDeserialize, - K: core::default::Default, - V: core::default::Default, + K: ::core::default::Default, + V: ::core::default::Default, { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok( + ::core::result::Result::Ok( Self( - core::default::Default::default(), - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::default::Default::default(), + ::deserialize_reader(reader)?, ), ) } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap new file mode 100644 index 000000000..d2c09ca42 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap @@ -0,0 +1,25 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for G +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, + U: ::core::default::Default, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + Self( + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + ::core::default::Default::default(), + ), + ) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap index 5abdae6be..3caa0dc1c 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap @@ -1,20 +1,20 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for G where K: borsh::de::BorshDeserialize, V: borsh::de::BorshDeserialize, - U: core::default::Default, + U: ::core::default::Default, { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok( + ::core::result::Result::Ok( Self( - borsh::BorshDeserialize::deserialize_reader(reader)?, - core::default::Default::default(), + as borsh::BorshDeserialize>::deserialize_reader(reader)?, + ::core::default::Default::default(), ), ) } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait-2.snap new file mode 100644 index 000000000..edc0aaa54 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait-2.snap @@ -0,0 +1,21 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for G1 +where + U: borsh::de::BorshDeserializeAsync, + K: ::core::default::Default, + V: ::core::default::Default, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + Self( + ::core::default::Default::default(), + ::deserialize_reader(reader).await?, + ), + ) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait.snap index 546931471..7110ab816 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for G1 where @@ -9,10 +9,10 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok( + ::core::result::Result::Ok( Self( - core::default::Default::default(), - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::default::Default::default(), + ::deserialize_reader(reader)?, ), ) } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async-2.snap new file mode 100644 index 000000000..d6174b721 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async-2.snap @@ -0,0 +1,19 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for G1 +where + U: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + Self( + ::core::default::Default::default(), + ::deserialize_reader(reader).await?, + ), + ) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async.snap new file mode 100644 index 000000000..3b6968bc9 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async.snap @@ -0,0 +1,21 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserialize for G1 +where + U: borsh::de::BorshDeserialize, + K: ::core::default::Default, + V: ::core::default::Default, +{ + fn deserialize_reader<__R: borsh::io::Read>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + Self( + ::core::default::Default::default(), + ::deserialize_reader(reader)?, + ), + ) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct-2.snap new file mode 100644 index 000000000..1a9ab454b --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct-2.snap @@ -0,0 +1,19 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for CRecC { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + a: ::deserialize_reader(reader) + .await?, + b: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap index 0dd795c39..2336313ce 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap @@ -1,14 +1,17 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for CRecC { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { - a: borsh::BorshDeserialize::deserialize_reader(reader)?, - b: borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::result::Result::Ok(Self { + a: ::deserialize_reader(reader)?, + b: as borsh::BorshDeserialize>::deserialize_reader(reader)?, }) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct-2.snap new file mode 100644 index 000000000..5b8829d6b --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct-2.snap @@ -0,0 +1,19 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for TupleA +where + T: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok( + Self( + ::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + ), + ) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct.snap index c1d69d951..8a5cdabd4 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for TupleA where @@ -9,10 +9,10 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok( + ::core::result::Result::Ok( Self( - borsh::BorshDeserialize::deserialize_reader(reader)?, - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, + ::deserialize_reader(reader)?, ), ) } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics-2.snap new file mode 100644 index 000000000..482878f49 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics-2.snap @@ -0,0 +1,23 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A +where + K: borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync, +{ + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics.snap index f2a8c7c4b..e1566514c 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A where @@ -10,9 +10,9 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::result::Result::Ok(Self { + x: as borsh::BorshDeserialize>::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, }) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct-2.snap new file mode 100644 index 000000000..c6676bac8 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct-2.snap @@ -0,0 +1,15 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::de::BorshDeserializeAsync for A { + async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: ::deserialize_reader(reader).await?, + y: ::deserialize_reader(reader) + .await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap index 6026d09f0..feaaa0d5e 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap @@ -1,14 +1,14 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::de::BorshDeserialize for A { fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::result::Result::Ok(Self { + x: ::deserialize_reader(reader)?, + y: ::deserialize_reader(reader)?, }) } } diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate-2.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate-2.snap new file mode 100644 index 000000000..8cc625bae --- /dev/null +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate-2.snap @@ -0,0 +1,20 @@ +--- +source: borsh-derive/src/internals/deserialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl reexporter::borsh::de::BorshDeserializeAsync for A { + async fn deserialize_reader<__R: reexporter::borsh::async_io::AsyncRead>( + reader: &mut __R, + ) -> ::core::result::Result { + ::core::result::Result::Ok(Self { + x: ::deserialize_reader( + reader, + ) + .await?, + y: ::deserialize_reader( + reader, + ) + .await?, + }) + } +} diff --git a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate.snap index ad7fb3788..5d2e208e6 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate.snap @@ -1,14 +1,16 @@ --- source: borsh-derive/src/internals/deserialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl reexporter::borsh::de::BorshDeserialize for A { fn deserialize_reader<__R: reexporter::borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { - x: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, - y: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, + ::core::result::Result::Ok(Self { + x: ::deserialize_reader(reader)?, + y: ::deserialize_reader( + reader, + )?, }) } } diff --git a/borsh-derive/src/internals/deserialize/unions/mod.rs b/borsh-derive/src/internals/deserialize/unions/mod.rs index 3806821bd..89200b4ea 100644 --- a/borsh-derive/src/internals/deserialize/unions/mod.rs +++ b/borsh-derive/src/internals/deserialize/unions/mod.rs @@ -1,6 +1,9 @@ use proc_macro2::TokenStream as TokenStream2; use syn::{ItemUnion, Path}; -pub fn process(_input: &ItemUnion, _cratename: Path) -> syn::Result { +pub fn process( + _input: ItemUnion, + _cratename: Path, +) -> syn::Result { unimplemented!() } diff --git a/borsh-derive/src/internals/enum_discriminant.rs b/borsh-derive/src/internals/enum_discriminant.rs index 03b3f5829..a3e8fcc94 100644 --- a/borsh-derive/src/internals/enum_discriminant.rs +++ b/borsh-derive/src/internals/enum_discriminant.rs @@ -1,8 +1,7 @@ -use std::collections::HashMap; -use std::convert::TryFrom; +use std::{collections::HashMap, convert::TryFrom}; use proc_macro2::{Ident, TokenStream}; -use quote::quote; +use quote::{quote, ToTokens}; use syn::{punctuated::Punctuated, token::Comma, Variant}; pub struct Discriminants(HashMap); @@ -15,8 +14,8 @@ impl Discriminants { for variant in variants { let this_discriminant = variant.discriminant.clone().map_or_else( - || quote! { #next_discriminant_if_not_specified }, - |(_, e)| quote! { #e }, + || next_discriminant_if_not_specified, + |(_, e)| e.into_token_stream(), ); next_discriminant_if_not_specified = quote! { #this_discriminant + 1 }; @@ -39,8 +38,7 @@ impl Discriminants { ) })?; let result = if use_discriminant { - let discriminant_value = self.0.get(variant_ident).unwrap(); - quote! { #discriminant_value } + self.0.get(variant_ident).unwrap().clone() // discriminant value } else { quote! { #variant_idx } }; diff --git a/borsh-derive/src/internals/generics.rs b/borsh-derive/src/internals/generics.rs index 7914b3b00..3b29bb4f2 100644 --- a/borsh-derive/src/internals/generics.rs +++ b/borsh-derive/src/internals/generics.rs @@ -1,9 +1,10 @@ use std::collections::{HashMap, HashSet}; -use quote::{quote, ToTokens}; +use quote::ToTokens; use syn::{ - punctuated::Pair, Field, GenericArgument, Generics, Ident, Macro, Path, PathArguments, - PathSegment, ReturnType, Type, TypeParamBound, TypePath, WhereClause, WherePredicate, + parse_quote, punctuated::Pair, Field, GenericArgument, Generics, Ident, Macro, Path, + PathArguments, PathSegment, ReturnType, Type, TypeParamBound, TypePath, WhereClause, + WherePredicate, }; pub fn default_where(where_clause: Option<&WhereClause>) -> WhereClause { @@ -20,10 +21,7 @@ pub fn compute_predicates(params: Vec, traitname: &Path) -> Vec, traitname: &Path) -> Vec Generics { - syn::Generics { +pub fn without_defaults(generics: Generics) -> Generics { + Generics { params: generics .params - .iter() + .into_iter() .map(|param| match param { syn::GenericParam::Type(param) => syn::GenericParam::Type(syn::TypeParam { eq_token: None, default: None, - ..param.clone() + ..param }), - _ => param.clone(), + _ => param, }) .collect(), - ..generics.clone() + ..generics } } diff --git a/borsh-derive/src/internals/schema/enums/mod.rs b/borsh-derive/src/internals/schema/enums/mod.rs index 95bbed06b..0d5394986 100644 --- a/borsh-derive/src/internals/schema/enums/mod.rs +++ b/borsh-derive/src/internals/schema/enums/mod.rs @@ -1,6 +1,7 @@ +use std::collections::HashSet; + use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, ToTokens}; -use std::collections::HashSet; use syn::{Fields, Generics, Ident, ItemEnum, ItemStruct, Path, Variant, Visibility}; use crate::internals::{ @@ -28,14 +29,14 @@ fn transform_variant_fields(mut input: Fields) -> Fields { input } -pub fn process(input: &ItemEnum, cratename: Path) -> syn::Result { +pub fn process(input: ItemEnum, cratename: Path) -> syn::Result { let name = &input.ident; let enum_name = name.to_token_stream().to_string(); - let generics = generics::without_defaults(&input.generics); + let use_discriminant = item::contains_use_discriminant(&input)?; + let generics = generics::without_defaults(input.generics); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let mut where_clause = generics::default_where(where_clause); let mut generics_output = schema::GenericsOutput::new(&generics); - let use_discriminant = item::contains_use_discriminant(input)?; let discriminants = Discriminants::new(&input.variants); // Generate functions that return the schema for variants. @@ -137,8 +138,8 @@ fn process_variant( }, variant_entry: quote! { (u8::from(#discriminant_value) as i64, - #variant_name.into(), - #variant_type::declaration()) + #variant_name.into(), + #variant_type::declaration()) }, }) } @@ -181,47 +182,46 @@ fn inner_struct_definition( #[cfg(test)] mod tests { + use syn::parse_quote; + + use super::*; use crate::internals::test_helpers::{ default_cratename, local_insta_assert_debug_snapshot, local_insta_assert_snapshot, pretty_print_syn_str, }; - use super::*; - #[test] fn simple_enum() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { Bacon, Eggs } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_enum_with_custom_crate() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { Bacon, Eggs } - }) - .unwrap(); + }; - let crate_: Path = syn::parse2(quote! { reexporter::borsh }).unwrap(); - let actual = process(&item_enum, crate_).unwrap(); + let crate_: Path = parse_quote! { reexporter::borsh }; + let actual = process(item_enum, crate_).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_discriminant_false() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(use_discriminant = false)] enum X { A, @@ -231,15 +231,14 @@ mod tests { E = 10, F, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_discriminant_true() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(use_discriminant = true)] enum X { A, @@ -249,61 +248,57 @@ mod tests { E = 10, F, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn single_field_enum() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { Bacon, } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn complex_enum() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { Bacon, Eggs, Salad(Tomatoes, Cucumber, Oil), Sausage{wrapper: Wrapper, filling: Filling}, } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn complex_enum_generics() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { Bacon, Eggs, Salad(Tomatoes, C, Oil), Sausage{wrapper: W, filling: Filling}, } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn trailing_comma_generics() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum Side where A: Display + Debug, @@ -312,16 +307,15 @@ mod tests { Left(A), Right(B), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn test_filter_foreign_attrs() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { #[serde(rename = "ab")] B { @@ -335,33 +329,31 @@ mod tests { beta: String, } } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn complex_enum_generics_borsh_skip_tuple_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where W: Hash { Bacon, Eggs, Salad(Tomatoes, #[borsh(skip)] C, Oil), Sausage{wrapper: W, filling: Filling}, } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn complex_enum_generics_borsh_skip_named_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { Bacon, Eggs, @@ -373,16 +365,15 @@ mod tests { unexpected: U, }, } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn recursive_enum() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { x: HashMap, @@ -390,17 +381,16 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum EnumParametrized where K: TraitName, @@ -415,16 +405,15 @@ mod tests { }, C(T, u16), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type_param_override() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum EnumParametrized where K: TraitName, @@ -440,17 +429,16 @@ mod tests { }, C(T, u16), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type_param_override_conflict() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum EnumParametrized where K: TraitName, @@ -462,17 +450,16 @@ mod tests { }, C(T, u16), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()); + let actual = process(item_enum, default_cratename()); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn check_with_funcs_skip_conflict() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum C { C3(u64, u64), C4( @@ -484,17 +471,16 @@ mod tests { ThirdParty, ), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()); + let actual = process(item_enum, default_cratename()); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn with_funcs_attr() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum C { C3(u64, u64), C4( @@ -506,11 +492,10 @@ mod tests { ThirdParty, ), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_enum, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } } diff --git a/borsh-derive/src/internals/schema/mod.rs b/borsh-derive/src/internals/schema/mod.rs index b094a4452..d1104d9d0 100644 --- a/borsh-derive/src/internals/schema/mod.rs +++ b/borsh-derive/src/internals/schema/mod.rs @@ -3,8 +3,8 @@ use std::collections::HashSet; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use syn::{ - punctuated::Punctuated, token::Comma, Field, Fields, GenericParam, Generics, Ident, Path, Type, - WherePredicate, + parse_quote, punctuated::Punctuated, token::Comma, Field, Fields, GenericParam, Generics, + Ident, Path, Type, WherePredicate, }; use crate::internals::{attributes::field, generics}; @@ -22,8 +22,9 @@ impl GenericsOutput { params_visitor: generics::FindTyParams::new(generics), } } + fn result(self, item_name: &str, cratename: &Path) -> (Vec, TokenStream2) { - let trait_path: Path = syn::parse2(quote! { #cratename::BorshSchema }).unwrap(); + let trait_path: Path = parse_quote! { #cratename::BorshSchema }; let predicates = generics::compute_predicates( self.params_visitor.clone().process_for_bounds(), &trait_path, @@ -48,13 +49,11 @@ fn declaration(ident_str: &str, cratename: Path, params_for_bounds: Vec) - }); } if declaration_params.is_empty() { - quote! { - #ident_str.to_string() - } + quote! { #ident_str.to_string() } } else { quote! { - let params = #cratename::__private::maybestd::vec![#(#declaration_params),*]; - format!(r#"{}<{}>"#, #ident_str, params.join(", ")) + let params = #cratename::__private::maybestd::vec![#(#declaration_params),*]; + format!(r#"{}<{}>"#, #ident_str, params.join(", ")) } } } diff --git a/borsh-derive/src/internals/schema/structs/mod.rs b/borsh-derive/src/internals/schema/structs/mod.rs index 8e388430f..19b09f5b6 100644 --- a/borsh-derive/src/internals/schema/structs/mod.rs +++ b/borsh-derive/src/internals/schema/structs/mod.rs @@ -1,6 +1,6 @@ use proc_macro2::TokenStream as TokenStream2; use quote::{quote, ToTokens}; -use syn::{ExprPath, Fields, Ident, ItemStruct, Path, Type}; +use syn::{parse_quote, ExprPath, Fields, Ident, ItemStruct, Path, Type}; use crate::internals::{attributes::field, generics, schema}; @@ -13,10 +13,9 @@ fn field_declaration_output( cratename: &Path, declaration_override: Option, ) -> TokenStream2 { - let default_path: ExprPath = - syn::parse2(quote! { <#field_type as #cratename::BorshSchema>::declaration }).unwrap(); + let default_path = || parse_quote! { <#field_type as #cratename::BorshSchema>::declaration }; - let path = declaration_override.unwrap_or(default_path); + let path = declaration_override.unwrap_or_else(default_path); if let Some(field_name) = field_name { let field_name = field_name.to_token_stream().to_string(); @@ -37,21 +36,19 @@ fn field_definitions_output( cratename: &Path, definitions_override: Option, ) -> TokenStream2 { - let default_path: ExprPath = syn::parse2( - quote! { <#field_type as #cratename::BorshSchema>::add_definitions_recursively }, - ) - .unwrap(); - let path = definitions_override.unwrap_or(default_path); + let default_path = + || parse_quote! { <#field_type as #cratename::BorshSchema>::add_definitions_recursively }; + let path = definitions_override.unwrap_or_else(default_path); quote! { #path(definitions); } } -pub fn process(input: &ItemStruct, cratename: Path) -> syn::Result { +pub fn process(input: ItemStruct, cratename: Path) -> syn::Result { let name = &input.ident; let struct_name = name.to_token_stream().to_string(); - let generics = generics::without_defaults(&input.generics); + let generics = generics::without_defaults(input.generics); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let mut where_clause = generics::default_where(where_clause); let mut generics_output = schema::GenericsOutput::new(&generics); @@ -135,6 +132,7 @@ fn process_fields( } Ok((struct_fields, add_definitions_recursively)) } + fn process_field( field: &syn::Field, cratename: &Path, @@ -162,103 +160,97 @@ fn process_field( #[cfg(test)] mod tests { + use syn::parse_quote; + + use super::*; use crate::internals::test_helpers::{ default_cratename, local_insta_assert_debug_snapshot, local_insta_assert_snapshot, pretty_print_syn_str, }; - use super::*; - #[test] fn unit_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A; - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn wrapper_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A(T); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn tuple_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A(u64, String); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn tuple_struct_params() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A(K, V); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: u64, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_struct_with_custom_crate() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: u64, y: String, } - }) - .unwrap(); + }; - let crate_: Path = syn::parse2(quote! { reexporter::borsh }).unwrap(); - let actual = process(&item_struct, crate_).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let crate_: Path = parse_quote! { reexporter::borsh }; + let actual = process(item_struct, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_generics() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: HashMap, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn trailing_comma_generics() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A where K: Display + Debug, @@ -266,130 +258,121 @@ mod tests { x: HashMap, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn tuple_struct_whole_skip() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A(#[borsh(skip)] String); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn tuple_struct_partial_skip() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A(#[borsh(skip)] u64, String); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip1() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G ( #[borsh(skip)] HashMap, U, ); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G ( HashMap, #[borsh(skip)] U, ); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip3() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G ( #[borsh(skip)] HashMap, U, K, ); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip4() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct ASalad(Tomatoes, #[borsh(skip)] C, Oil); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_named_fields_struct_borsh_skip() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G { #[borsh(skip)] x: HashMap, y: U, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn recursive_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct CRecC { a: String, b: HashMap, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -397,17 +380,16 @@ mod tests { field: T::Associated, another: V, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type_param_override() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -418,17 +400,16 @@ mod tests { field: ::Associated, another: V, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type_param_override2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -439,17 +420,16 @@ mod tests { field: (::Associated, T), another: V, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type_param_override_conflict() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -460,17 +440,16 @@ mod tests { field: ::Associated, another: V, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()); + let actual = process(item_struct, default_cratename()); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn check_with_funcs_skip_conflict() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(skip,schema(with_funcs( declaration = "third_party_impl::declaration::", @@ -479,17 +458,16 @@ mod tests { x: ThirdParty, y: u64, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()); + let actual = process(item_struct, default_cratename()); local_insta_assert_debug_snapshot!(actual.unwrap_err()); } #[test] fn with_funcs_attr() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(schema(with_funcs( declaration = "third_party_impl::declaration::", @@ -498,17 +476,16 @@ mod tests { x: ThirdParty, y: u64, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn schema_param_override3() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh( schema( @@ -518,11 +495,10 @@ mod tests { x: PrimaryMap, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } } diff --git a/borsh-derive/src/internals/serialize/enums/mod.rs b/borsh-derive/src/internals/serialize/enums/mod.rs index 4e86ca2d4..0eee414f3 100644 --- a/borsh-derive/src/internals/serialize/enums/mod.rs +++ b/borsh-derive/src/internals/serialize/enums/mod.rs @@ -1,6 +1,6 @@ -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{Fields, Ident, ItemEnum, Path, Variant}; +use syn::{Fields, Ident, ItemEnum, Lifetime, Path, Token, Variant}; use crate::internals::{ attributes::{field, item, BoundType}, @@ -8,22 +8,25 @@ use crate::internals::{ generics, serialize, }; -pub fn process(input: &ItemEnum, cratename: Path) -> syn::Result { +pub fn process( + input: ItemEnum, + cratename: Path, +) -> syn::Result { let enum_ident = &input.ident; - let generics = generics::without_defaults(&input.generics); + let use_discriminant = item::contains_use_discriminant(&input)?; + let generics = generics::without_defaults(input.generics); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let mut where_clause = generics::default_where(where_clause); let mut generics_output = serialize::GenericsOutput::new(&generics); let mut all_variants_idx_body = TokenStream2::new(); let mut fields_body = TokenStream2::new(); - let use_discriminant = item::contains_use_discriminant(input)?; let discriminants = Discriminants::new(&input.variants); let mut has_unit_variant = false; for (variant_idx, variant) in input.variants.iter().enumerate() { let variant_ident = &variant.ident; let discriminant_value = discriminants.get(variant_ident, use_discriminant, variant_idx)?; - let variant_output = process_variant( + let variant_output = process_variant::( variant, enum_ident, &discriminant_value, @@ -41,18 +44,44 @@ pub fn process(input: &ItemEnum, cratename: Path) -> syn::Result { } } let fields_body = optimize_fields_body(fields_body, has_unit_variant); - generics_output.extend(&mut where_clause, &cratename); + generics_output.extend::(&mut where_clause, &cratename); + + let serialize_trait = Ident::new( + if IS_ASYNC { + "BorshSerializeAsync" + } else { + "BorshSerialize" + }, + Span::call_site(), + ); + let writer_trait = if IS_ASYNC { + quote! { async_io::AsyncWrite } + } else { + quote! { io::Write } + }; + let r#async = IS_ASYNC.then(|| Token![async](Span::call_site())); + let lifetime = IS_ASYNC.then(|| Lifetime::new("'async_variant", Span::call_site())); + let lt_comma = IS_ASYNC.then(|| Token![,](Span::call_site())); + + let write_variant_idx = if IS_ASYNC { + quote! { writer.write_u8(variant_idx).await } + } else { + quote! { writer.write_all(&variant_idx.to_le_bytes()) } + }; Ok(quote! { - impl #impl_generics #cratename::ser::BorshSerialize for #enum_ident #ty_generics #where_clause { - fn serialize<__W: #cratename::io::Write>(&self, writer: &mut __W) -> ::core::result::Result<(), #cratename::io::Error> { + impl #impl_generics #cratename::ser::#serialize_trait for #enum_ident #ty_generics #where_clause { + #r#async fn serialize<#lifetime #lt_comma __W: #cratename::#writer_trait>( + &#lifetime self, + writer: &#lifetime mut __W, + ) -> ::core::result::Result<(), #cratename::io::Error> { let variant_idx: u8 = match self { #all_variants_idx_body }; - writer.write_all(&variant_idx.to_le_bytes())?; + #write_variant_idx?; #fields_body - Ok(()) + ::core::result::Result::Ok(()) } } }) @@ -123,7 +152,7 @@ struct VariantOutput { variant_idx_body: TokenStream2, } -fn process_variant( +fn process_variant( variant: &Variant, enum_ident: &Ident, discriminant_value: &TokenStream2, @@ -136,7 +165,13 @@ fn process_variant( let mut variant_fields = VariantFields::default(); for field in &fields.named { let field_id = serialize::FieldId::Enum(field.ident.clone().unwrap()); - process_field(field, field_id, cratename, generics, &mut variant_fields)?; + process_field::( + field, + field_id, + cratename, + generics, + &mut variant_fields, + )?; } VariantOutput { body: VariantBody::Fields(variant_fields.named_header()), @@ -149,7 +184,13 @@ fn process_variant( let mut variant_fields = VariantFields::default(); for (field_idx, field) in fields.unnamed.iter().enumerate() { let field_id = serialize::FieldId::new_enum_unnamed(field_idx)?; - process_field(field, field_id, cratename, generics, &mut variant_fields)?; + process_field::( + field, + field_id, + cratename, + generics, + &mut variant_fields, + )?; } VariantOutput { body: VariantBody::Fields(variant_fields.unnamed_header()), @@ -168,7 +209,7 @@ fn process_variant( Ok(variant_output) } -fn process_field( +fn process_field( field: &syn::Field, field_id: serialize::FieldId, cratename: &Path, @@ -177,10 +218,16 @@ fn process_field( ) -> syn::Result<()> { let parsed = field::Attributes::parse(&field.attrs)?; - let needs_bounds_derive = parsed.needs_bounds_derive(BoundType::Serialize); - generics - .overrides - .extend(parsed.collect_bounds(BoundType::Serialize)); + let needs_bounds_derive = if IS_ASYNC { + parsed.needs_async_bounds_derive(BoundType::Serialize) + } else { + parsed.needs_bounds_derive(BoundType::Serialize) + }; + generics.overrides.extend(if IS_ASYNC { + parsed.collect_async_bounds(BoundType::Serialize) + } else { + parsed.collect_bounds(BoundType::Serialize) + }); let field_variant_header = field_id.enum_variant_header(parsed.skip); if let Some(field_variant_header) = field_variant_header { @@ -188,7 +235,15 @@ fn process_field( } if !parsed.skip { - let delta = field_id.serialize_output(cratename, parsed.serialize_with); + let delta = field_id.serialize_output::( + &field.ty, + cratename, + if IS_ASYNC { + parsed.serialize_with_async + } else { + parsed.serialize_with + }, + ); output.body.extend(delta); if needs_bounds_derive { generics.serialize_visitor.visit_field(field); @@ -199,14 +254,15 @@ fn process_field( #[cfg(test)] mod tests { + use syn::parse_quote; + + use super::*; use crate::internals::test_helpers::{ default_cratename, local_insta_assert_snapshot, pretty_print_syn_str, }; - - use super::*; #[test] fn borsh_skip_tuple_variant_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AATTB { B(#[borsh(skip)] i32, #[borsh(skip)] u32), @@ -214,16 +270,18 @@ mod tests { beta: u8, } } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn struct_variant_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AB { B { c: i32, @@ -234,17 +292,18 @@ mod tests { beta: String, } } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_enum_with_custom_crate() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AB { B { c: i32, @@ -255,18 +314,20 @@ mod tests { beta: String, } } - }) - .unwrap(); + }; + + let crate_: Path = parse_quote! { reexporter::borsh }; - let crate_: Path = syn::parse2(quote! { reexporter::borsh }).unwrap(); - let actual = process(&item_enum, crate_).unwrap(); + let actual = process::(item_enum.clone(), crate_.clone()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_skip_struct_variant_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AB { B { @@ -280,17 +341,18 @@ mod tests { beta: String, } } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_skip_struct_variant_all_fields() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AAB { B { @@ -305,17 +367,18 @@ mod tests { beta: String, } } - }) - .unwrap(); + }; - let actual = process(&item_enum, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_generics() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { B { x: HashMap, @@ -323,16 +386,18 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn bound_generics() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { x: HashMap, @@ -340,16 +405,18 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn recursive_enum() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { x: HashMap, @@ -357,17 +424,18 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_borsh_skip_struct_field() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { #[borsh(skip)] @@ -376,17 +444,18 @@ mod tests { }, C(K, Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_borsh_skip_tuple_field() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A where V: Value { B { x: HashMap, @@ -394,17 +463,18 @@ mod tests { }, C(K, #[borsh(skip)] Vec), } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_serialize_bound() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { C { a: String, @@ -416,17 +486,41 @@ mod tests { }, D(u32, u32), } - }) - .unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn generic_serialize_async_bound() { + let item_enum: ItemEnum = parse_quote! { + enum A { + C { + a: String, + #[borsh(async_bound(serialize = + "T: borsh::ser::BorshSerializeAsync + PartialOrd, + U: borsh::ser::BorshSerializeAsync" + ))] + b: HashMap, + }, + D(u32, u32), + } + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn check_serialize_with_attr() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum C { C3(u64, u64), C4 { @@ -435,17 +529,38 @@ mod tests { y: ThirdParty }, } - }) - .unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn check_serialize_with_async_attr() { + let item_enum: ItemEnum = parse_quote! { + enum C { + C3(u64, u64), + C4 { + x: u64, + #[borsh(serialize_with_async = "third_party_impl::serialize_third_party")] + y: ThirdParty + }, + } + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_discriminant_false() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(use_discriminant = false)] enum X { A, @@ -455,15 +570,17 @@ mod tests { E = 10, F, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn borsh_discriminant_true() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(use_discriminant = true)] enum X { A, @@ -473,26 +590,30 @@ mod tests { E = 10, F, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn mixed_with_unit_variants() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum X { A(u16), B, C {x: i32, y: i32}, D, } - }) - .unwrap(); - let actual = process(&item_enum, default_cratename()).unwrap(); + }; + + let actual = process::(item_enum.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false-2.snap new file mode 100644 index 000000000..0722ddbcd --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false-2.snap @@ -0,0 +1,21 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for X { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + X::A => 0u8, + X::B => 1u8, + X::C => 2u8, + X::D => 3u8, + X::E => 4u8, + X::F => 5u8, + }; + writer.write_u8(variant_idx).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false.snap index 05e1f88e9..f7d142a0a 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for X { fn serialize<__W: borsh::io::Write>( @@ -16,6 +16,6 @@ impl borsh::ser::BorshSerialize for X { X::F => 5u8, }; writer.write_all(&variant_idx.to_le_bytes())?; - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true-2.snap new file mode 100644 index 000000000..f2067c71f --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true-2.snap @@ -0,0 +1,21 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for X { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + X::A => 0, + X::B => 20, + X::C => 20 + 1, + X::D => 20 + 1 + 1, + X::E => 10, + X::F => 10 + 1, + }; + writer.write_u8(variant_idx).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true.snap index ee3371232..51e3dedaa 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for X { fn serialize<__W: borsh::io::Write>( @@ -16,6 +16,6 @@ impl borsh::ser::BorshSerialize for X { X::F => 10 + 1, }; writer.write_all(&variant_idx.to_le_bytes())?; - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields-2.snap new file mode 100644 index 000000000..9160687b9 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields-2.snap @@ -0,0 +1,23 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for AAB { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + AAB::B { .. } => 0u8, + AAB::NegatedVariant { .. } => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + AAB::B { .. } => {} + AAB::NegatedVariant { beta, .. } => { + ::serialize(beta, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap index b8943a467..359f454b5 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for AAB { fn serialize<__W: borsh::io::Write>( @@ -15,9 +15,9 @@ impl borsh::ser::BorshSerialize for AAB { match self { AAB::B { .. } => {} AAB::NegatedVariant { beta, .. } => { - borsh::BorshSerialize::serialize(beta, writer)?; + ::serialize(beta, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap new file mode 100644 index 000000000..1a0b50e04 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap @@ -0,0 +1,25 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for AB { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + AB::B { .. } => 0u8, + AB::NegatedVariant { .. } => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + AB::B { d, .. } => { + ::serialize(d, writer).await?; + } + AB::NegatedVariant { beta, .. } => { + ::serialize(beta, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field.snap index f5ff6946d..a8b419de0 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for AB { fn serialize<__W: borsh::io::Write>( @@ -14,12 +14,12 @@ impl borsh::ser::BorshSerialize for AB { writer.write_all(&variant_idx.to_le_bytes())?; match self { AB::B { d, .. } => { - borsh::BorshSerialize::serialize(d, writer)?; + ::serialize(d, writer)?; } AB::NegatedVariant { beta, .. } => { - borsh::BorshSerialize::serialize(beta, writer)?; + ::serialize(beta, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap new file mode 100644 index 000000000..cef5665fe --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap @@ -0,0 +1,23 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for AATTB { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + AATTB::B(..) => 0u8, + AATTB::NegatedVariant { .. } => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + AATTB::B(_id0, _id1) => {} + AATTB::NegatedVariant { beta, .. } => { + ::serialize(beta, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field.snap index fc3be0087..82b5f7b48 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for AATTB { fn serialize<__W: borsh::io::Write>( @@ -15,9 +15,9 @@ impl borsh::ser::BorshSerialize for AATTB { match self { AATTB::B(_id0, _id1) => {} AATTB::NegatedVariant { beta, .. } => { - borsh::BorshSerialize::serialize(beta, writer)?; + ::serialize(beta, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics-2.snap new file mode 100644 index 000000000..86c05d8ca --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics-2.snap @@ -0,0 +1,34 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + V: Value, + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::B { .. } => 0u8, + A::C(..) => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + A::B { x, y, .. } => { + as borsh::BorshSerializeAsync>::serialize(x, writer) + .await?; + ::serialize(y, writer).await?; + } + A::C(id0, id1) => { + ::serialize(id0, writer).await?; + as borsh::BorshSerializeAsync>::serialize(id1, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics.snap b/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics.snap index 9c1630967..10e186ddc 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -20,14 +20,14 @@ where writer.write_all(&variant_idx.to_le_bytes())?; match self { A::B { x, y, .. } => { - borsh::BorshSerialize::serialize(x, writer)?; - borsh::BorshSerialize::serialize(y, writer)?; + as borsh::BorshSerialize>::serialize(x, writer)?; + ::serialize(y, writer)?; } A::C(id0, id1) => { - borsh::BorshSerialize::serialize(id0, writer)?; - borsh::BorshSerialize::serialize(id1, writer)?; + ::serialize(id0, writer)?; + as borsh::BorshSerialize>::serialize(id1, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr-2.snap new file mode 100644 index 000000000..e7cb8b20d --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr-2.snap @@ -0,0 +1,31 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for C +where + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + C::C3(..) => 0u8, + C::C4 { .. } => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + C::C3(id0, id1) => { + ::serialize(id0, writer).await?; + ::serialize(id1, writer).await?; + } + C::C4 { x, y, .. } => { + ::serialize(x, writer).await?; + third_party_impl::serialize_third_party(y, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr.snap b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr.snap new file mode 100644 index 000000000..9206b7b6d --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr.snap @@ -0,0 +1,31 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerialize for C +where + K: borsh::ser::BorshSerialize, + V: borsh::ser::BorshSerialize, +{ + fn serialize<__W: borsh::io::Write>( + &self, + writer: &mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + C::C3(..) => 0u8, + C::C4 { .. } => 1u8, + }; + writer.write_all(&variant_idx.to_le_bytes())?; + match self { + C::C3(id0, id1) => { + ::serialize(id0, writer)?; + ::serialize(id1, writer)?; + } + C::C4 { x, y, .. } => { + ::serialize(x, writer)?; + as borsh::BorshSerialize>::serialize(y, writer)?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr-2.snap new file mode 100644 index 000000000..9bd53ef66 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr-2.snap @@ -0,0 +1,32 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for C +where + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + C::C3(..) => 0u8, + C::C4 { .. } => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + C::C3(id0, id1) => { + ::serialize(id0, writer).await?; + ::serialize(id1, writer).await?; + } + C::C4 { x, y, .. } => { + ::serialize(x, writer).await?; + as borsh::BorshSerializeAsync>::serialize(y, writer) + .await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr.snap b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr.snap index 29f1619c1..84fc5e517 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for C where @@ -18,14 +18,14 @@ where writer.write_all(&variant_idx.to_le_bytes())?; match self { C::C3(id0, id1) => { - borsh::BorshSerialize::serialize(id0, writer)?; - borsh::BorshSerialize::serialize(id1, writer)?; + ::serialize(id0, writer)?; + ::serialize(id1, writer)?; } C::C4 { x, y, .. } => { - borsh::BorshSerialize::serialize(x, writer)?; + ::serialize(x, writer)?; third_party_impl::serialize_third_party(y, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap new file mode 100644 index 000000000..8d186deb4 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap @@ -0,0 +1,31 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + V: Value, + K: borsh::ser::BorshSerializeAsync, + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::B { .. } => 0u8, + A::C(..) => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + A::B { y, .. } => { + ::serialize(y, writer).await?; + } + A::C(id0, id1) => { + ::serialize(id0, writer).await?; + as borsh::BorshSerializeAsync>::serialize(id1, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap index 051033a64..0fc2c601a 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -19,13 +19,13 @@ where writer.write_all(&variant_idx.to_le_bytes())?; match self { A::B { y, .. } => { - borsh::BorshSerialize::serialize(y, writer)?; + ::serialize(y, writer)?; } A::C(id0, id1) => { - borsh::BorshSerialize::serialize(id0, writer)?; - borsh::BorshSerialize::serialize(id1, writer)?; + ::serialize(id0, writer)?; + as borsh::BorshSerialize>::serialize(id1, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap new file mode 100644 index 000000000..b260874c3 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap @@ -0,0 +1,32 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + V: Value, + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::B { .. } => 0u8, + A::C(..) => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + A::B { x, y, .. } => { + as borsh::BorshSerializeAsync>::serialize(x, writer) + .await?; + ::serialize(y, writer).await?; + } + A::C(id0, _id1) => { + ::serialize(id0, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap index 4f0ae41b7..ca61b5fb9 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -19,13 +19,13 @@ where writer.write_all(&variant_idx.to_le_bytes())?; match self { A::B { x, y, .. } => { - borsh::BorshSerialize::serialize(x, writer)?; - borsh::BorshSerialize::serialize(y, writer)?; + as borsh::BorshSerialize>::serialize(x, writer)?; + ::serialize(y, writer)?; } A::C(id0, _id1) => { - borsh::BorshSerialize::serialize(id0, writer)?; + ::serialize(id0, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound-2.snap new file mode 100644 index 000000000..9d4f4b821 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound-2.snap @@ -0,0 +1,32 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + T: borsh::ser::BorshSerializeAsync + PartialOrd, + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::C { .. } => 0u8, + A::D(..) => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + A::C { a, b, .. } => { + ::serialize(a, writer).await?; + as borsh::BorshSerializeAsync>::serialize(b, writer) + .await?; + } + A::D(id0, id1) => { + ::serialize(id0, writer).await?; + ::serialize(id1, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound.snap new file mode 100644 index 000000000..23806f9c5 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound.snap @@ -0,0 +1,31 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerialize for A +where + T: borsh::ser::BorshSerialize, + U: borsh::ser::BorshSerialize, +{ + fn serialize<__W: borsh::io::Write>( + &self, + writer: &mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::C { .. } => 0u8, + A::D(..) => 1u8, + }; + writer.write_all(&variant_idx.to_le_bytes())?; + match self { + A::C { a, b, .. } => { + ::serialize(a, writer)?; + as borsh::BorshSerialize>::serialize(b, writer)?; + } + A::D(id0, id1) => { + ::serialize(id0, writer)?; + ::serialize(id1, writer)?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound-2.snap new file mode 100644 index 000000000..e3374b186 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound-2.snap @@ -0,0 +1,32 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + T: borsh::ser::BorshSerializeAsync, + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::C { .. } => 0u8, + A::D(..) => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + A::C { a, b, .. } => { + ::serialize(a, writer).await?; + as borsh::BorshSerializeAsync>::serialize(b, writer) + .await?; + } + A::D(id0, id1) => { + ::serialize(id0, writer).await?; + ::serialize(id1, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound.snap index 1e53690ec..91fd4f8fe 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -18,14 +18,14 @@ where writer.write_all(&variant_idx.to_le_bytes())?; match self { A::C { a, b, .. } => { - borsh::BorshSerialize::serialize(a, writer)?; - borsh::BorshSerialize::serialize(b, writer)?; + ::serialize(a, writer)?; + as borsh::BorshSerialize>::serialize(b, writer)?; } A::D(id0, id1) => { - borsh::BorshSerialize::serialize(id0, writer)?; - borsh::BorshSerialize::serialize(id1, writer)?; + ::serialize(id0, writer)?; + ::serialize(id1, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants-2.snap new file mode 100644 index 000000000..c1155e80c --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants-2.snap @@ -0,0 +1,29 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for X { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + X::A(..) => 0u8, + X::B => 1u8, + X::C { .. } => 2u8, + X::D => 3u8, + }; + writer.write_u8(variant_idx).await?; + match self { + X::A(id0) => { + ::serialize(id0, writer).await?; + } + X::C { x, y, .. } => { + ::serialize(x, writer).await?; + ::serialize(y, writer).await?; + } + _ => {} + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants.snap b/borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants.snap index 69a56d5b9..687e4d815 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for X { fn serialize<__W: borsh::io::Write>( @@ -16,14 +16,14 @@ impl borsh::ser::BorshSerialize for X { writer.write_all(&variant_idx.to_le_bytes())?; match self { X::A(id0) => { - borsh::BorshSerialize::serialize(id0, writer)?; + ::serialize(id0, writer)?; } X::C { x, y, .. } => { - borsh::BorshSerialize::serialize(x, writer)?; - borsh::BorshSerialize::serialize(y, writer)?; + ::serialize(x, writer)?; + ::serialize(y, writer)?; } _ => {} } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum-2.snap new file mode 100644 index 000000000..124234ea6 --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum-2.snap @@ -0,0 +1,33 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + V: Value, + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::B { .. } => 0u8, + A::C(..) => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + A::B { x, y, .. } => { + as borsh::BorshSerializeAsync>::serialize(x, writer) + .await?; + ::serialize(y, writer).await?; + } + A::C(id0, id1) => { + ::serialize(id0, writer).await?; + as borsh::BorshSerializeAsync>::serialize(id1, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum.snap b/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum.snap index d7aeab233..6724928e5 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -19,14 +19,14 @@ where writer.write_all(&variant_idx.to_le_bytes())?; match self { A::B { x, y, .. } => { - borsh::BorshSerialize::serialize(x, writer)?; - borsh::BorshSerialize::serialize(y, writer)?; + as borsh::BorshSerialize>::serialize(x, writer)?; + ::serialize(y, writer)?; } A::C(id0, id1) => { - borsh::BorshSerialize::serialize(id0, writer)?; - borsh::BorshSerialize::serialize(id1, writer)?; + ::serialize(id0, writer)?; + as borsh::BorshSerialize>::serialize(id1, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate-2.snap new file mode 100644 index 000000000..4789105cf --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate-2.snap @@ -0,0 +1,32 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl reexporter::borsh::ser::BorshSerializeAsync for AB { + async fn serialize<'async_variant, __W: reexporter::borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), reexporter::borsh::io::Error> { + let variant_idx: u8 = match self { + AB::B { .. } => 0u8, + AB::NegatedVariant { .. } => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + AB::B { c, d, .. } => { + ::serialize(c, writer) + .await?; + ::serialize(d, writer) + .await?; + } + AB::NegatedVariant { beta, .. } => { + ::serialize( + beta, + writer, + ) + .await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap b/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap index fcfc55df6..d16e4ea5e 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl reexporter::borsh::ser::BorshSerialize for AB { fn serialize<__W: reexporter::borsh::io::Write>( @@ -14,13 +14,13 @@ impl reexporter::borsh::ser::BorshSerialize for AB { writer.write_all(&variant_idx.to_le_bytes())?; match self { AB::B { c, d, .. } => { - reexporter::borsh::BorshSerialize::serialize(c, writer)?; - reexporter::borsh::BorshSerialize::serialize(d, writer)?; + ::serialize(c, writer)?; + ::serialize(d, writer)?; } AB::NegatedVariant { beta, .. } => { - reexporter::borsh::BorshSerialize::serialize(beta, writer)?; + ::serialize(beta, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics-2.snap new file mode 100644 index 000000000..3f495c06c --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics-2.snap @@ -0,0 +1,33 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + A::B { .. } => 0u8, + A::C(..) => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + A::B { x, y, .. } => { + as borsh::BorshSerializeAsync>::serialize(x, writer) + .await?; + ::serialize(y, writer).await?; + } + A::C(id0, id1) => { + ::serialize(id0, writer).await?; + as borsh::BorshSerializeAsync>::serialize(id1, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics.snap b/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics.snap index 70e2f6498..8d056af5e 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -19,14 +19,14 @@ where writer.write_all(&variant_idx.to_le_bytes())?; match self { A::B { x, y, .. } => { - borsh::BorshSerialize::serialize(x, writer)?; - borsh::BorshSerialize::serialize(y, writer)?; + as borsh::BorshSerialize>::serialize(x, writer)?; + ::serialize(y, writer)?; } A::C(id0, id1) => { - borsh::BorshSerialize::serialize(id0, writer)?; - borsh::BorshSerialize::serialize(id1, writer)?; + ::serialize(id0, writer)?; + as borsh::BorshSerialize>::serialize(id1, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field-2.snap b/borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field-2.snap new file mode 100644 index 000000000..4c8428aaf --- /dev/null +++ b/borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field-2.snap @@ -0,0 +1,26 @@ +--- +source: borsh-derive/src/internals/serialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for AB { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + let variant_idx: u8 = match self { + AB::B { .. } => 0u8, + AB::NegatedVariant { .. } => 1u8, + }; + writer.write_u8(variant_idx).await?; + match self { + AB::B { c, d, .. } => { + ::serialize(c, writer).await?; + ::serialize(d, writer).await?; + } + AB::NegatedVariant { beta, .. } => { + ::serialize(beta, writer).await?; + } + } + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field.snap b/borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field.snap index 0ba345286..893d4794b 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/enums/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for AB { fn serialize<__W: borsh::io::Write>( @@ -14,13 +14,13 @@ impl borsh::ser::BorshSerialize for AB { writer.write_all(&variant_idx.to_le_bytes())?; match self { AB::B { c, d, .. } => { - borsh::BorshSerialize::serialize(c, writer)?; - borsh::BorshSerialize::serialize(d, writer)?; + ::serialize(c, writer)?; + ::serialize(d, writer)?; } AB::NegatedVariant { beta, .. } => { - borsh::BorshSerialize::serialize(beta, writer)?; + ::serialize(beta, writer)?; } } - Ok(()) + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/mod.rs b/borsh-derive/src/internals/serialize/mod.rs index b4b7a20dc..1ae0d4172 100644 --- a/borsh-derive/src/internals/serialize/mod.rs +++ b/borsh-derive/src/internals/serialize/mod.rs @@ -1,7 +1,8 @@ +use std::convert::TryFrom; + use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; -use std::convert::TryFrom; -use syn::{Expr, ExprPath, Generics, Ident, Index, Path}; +use syn::{parse_quote, Expr, ExprPath, Generics, Ident, Index, Path, Type}; use super::generics; @@ -21,8 +22,12 @@ impl GenericsOutput { serialize_visitor: generics::FindTyParams::new(generics), } } - fn extend(self, where_clause: &mut syn::WhereClause, cratename: &Path) { - let trait_path: Path = syn::parse2(quote! { #cratename::ser::BorshSerialize }).unwrap(); + fn extend(self, where_clause: &mut syn::WhereClause, cratename: &Path) { + let trait_path: Path = if IS_ASYNC { + parse_quote! { #cratename::ser::BorshSerializeAsync } + } else { + parse_quote! { #cratename::ser::BorshSerialize } + }; let predicates = generics::compute_predicates(self.serialize_visitor.process_for_bounds(), &trait_path); where_clause.predicates.extend(predicates); @@ -65,39 +70,54 @@ impl FieldId { impl FieldId { fn serialize_arg(&self) -> Expr { match self { - Self::Struct(name) => syn::parse2(quote! { &self.#name }).unwrap(), - Self::StructUnnamed(index) => syn::parse2(quote! { &self.#index }).unwrap(), - Self::Enum(name) => syn::parse2(quote! { #name }).unwrap(), + Self::Struct(name) => parse_quote! { &self.#name }, + Self::StructUnnamed(index) => parse_quote! { &self.#index }, + Self::Enum(name) => parse_quote! { #name }, Self::EnumUnnamed(ind) => { let field = Ident::new(&format!("id{}", ind.index), Span::mixed_site()); - syn::parse2(quote! { #field }).unwrap() + parse_quote! { #field } } } } + /// function which computes derive output [proc_macro2::TokenStream] /// of code, which serializes single field - pub fn serialize_output( + pub fn serialize_output( &self, + field_type: &Type, cratename: &Path, serialize_with: Option, ) -> TokenStream2 { let arg: Expr = self.serialize_arg(); + let dot_await = IS_ASYNC.then(|| quote! { .await }); if let Some(func) = serialize_with { - quote! { #func(#arg, writer)?; } + quote! { #func(#arg, writer)#dot_await?; } } else { - quote! { #cratename::BorshSerialize::serialize(#arg, writer)?; } + let serialize_trait = Ident::new( + if IS_ASYNC { + "BorshSerializeAsync" + } else { + "BorshSerialize" + }, + Span::call_site(), + ); + quote! { <#field_type as #cratename::#serialize_trait>::serialize(#arg, writer)#dot_await?; } } } + pub fn enum_variant_header(&self, skipped: bool) -> Option { match self { Self::Struct(..) | Self::StructUnnamed(..) => unreachable!("no variant header"), Self::Enum(name) => (!skipped).then_some(quote! { #name, }), Self::EnumUnnamed(index) => { - let field_ident = if skipped { - Ident::new(&format!("_id{}", index.index), Span::mixed_site()) - } else { - Ident::new(&format!("id{}", index.index), Span::mixed_site()) - }; + let field_ident = Ident::new( + &if skipped { + format!("_id{}", index.index) + } else { + format!("id{}", index.index) + }, + Span::mixed_site(), + ); Some(quote! { #field_ident, }) } } diff --git a/borsh-derive/src/internals/serialize/structs/mod.rs b/borsh-derive/src/internals/serialize/structs/mod.rs index 2864c78e9..75dc88893 100644 --- a/borsh-derive/src/internals/serialize/structs/mod.rs +++ b/borsh-derive/src/internals/serialize/structs/mod.rs @@ -1,15 +1,18 @@ -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{Fields, ItemStruct, Path}; +use syn::{Fields, ItemStruct, Lifetime, Path, Token}; use crate::internals::{ attributes::{field, BoundType}, generics, serialize, }; -pub fn process(input: &ItemStruct, cratename: Path) -> syn::Result { +pub fn process( + input: ItemStruct, + cratename: Path, +) -> syn::Result { let name = &input.ident; - let generics = generics::without_defaults(&input.generics); + let generics = generics::without_defaults(input.generics); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let mut where_clause = generics::default_where(where_clause); let mut body = TokenStream2::new(); @@ -19,31 +22,63 @@ pub fn process(input: &ItemStruct, cratename: Path) -> syn::Result for field in &fields.named { let field_id = serialize::FieldId::Struct(field.ident.clone().unwrap()); - process_field(field, field_id, &cratename, &mut generics_output, &mut body)?; + process_field::( + field, + field_id, + &cratename, + &mut generics_output, + &mut body, + )?; } } Fields::Unnamed(fields) => { for (field_idx, field) in fields.unnamed.iter().enumerate() { let field_id = serialize::FieldId::new_struct_unnamed(field_idx)?; - process_field(field, field_id, &cratename, &mut generics_output, &mut body)?; + process_field::( + field, + field_id, + &cratename, + &mut generics_output, + &mut body, + )?; } } Fields::Unit => {} } - generics_output.extend(&mut where_clause, &cratename); + generics_output.extend::(&mut where_clause, &cratename); + + let serialize_trait = Ident::new( + if IS_ASYNC { + "BorshSerializeAsync" + } else { + "BorshSerialize" + }, + Span::call_site(), + ); + let writer_trait_path = if IS_ASYNC { + quote! { async_io::AsyncWrite } + } else { + quote! { io::Write } + }; + let r#async = IS_ASYNC.then(|| Token![async](Span::call_site())); + let lifetime = IS_ASYNC.then(|| Lifetime::new("'async_variant", Span::call_site())); + let lt_comma = IS_ASYNC.then(|| Token![,](Span::call_site())); Ok(quote! { - impl #impl_generics #cratename::ser::BorshSerialize for #name #ty_generics #where_clause { - fn serialize<__W: #cratename::io::Write>(&self, writer: &mut __W) -> ::core::result::Result<(), #cratename::io::Error> { + impl #impl_generics #cratename::ser::#serialize_trait for #name #ty_generics #where_clause { + #r#async fn serialize<#lifetime #lt_comma __W: #cratename::#writer_trait_path>( + &#lifetime self, + writer: &#lifetime mut __W, + ) -> ::core::result::Result<(), #cratename::io::Error> { #body - Ok(()) + ::core::result::Result::Ok(()) } } }) } -fn process_field( +fn process_field( field: &syn::Field, field_id: serialize::FieldId, cratename: &Path, @@ -51,13 +86,28 @@ fn process_field( body: &mut TokenStream2, ) -> syn::Result<()> { let parsed = field::Attributes::parse(&field.attrs)?; - let needs_bounds_derive = parsed.needs_bounds_derive(BoundType::Serialize); - generics - .overrides - .extend(parsed.collect_bounds(BoundType::Serialize)); + let needs_bounds_derive = if IS_ASYNC { + parsed.needs_async_bounds_derive(BoundType::Serialize) + } else { + parsed.needs_bounds_derive(BoundType::Serialize) + }; + generics.overrides.extend(if IS_ASYNC { + parsed.collect_async_bounds(BoundType::Serialize) + } else { + parsed.collect_bounds(BoundType::Serialize) + }); + if !parsed.skip { - let delta = field_id.serialize_output(cratename, parsed.serialize_with); + let delta = field_id.serialize_output::( + &field.ty, + cratename, + if IS_ASYNC { + parsed.serialize_with_async + } else { + parsed.serialize_with + }, + ); body.extend(delta); if needs_bounds_derive { @@ -69,149 +119,163 @@ fn process_field( #[cfg(test)] mod tests { + use syn::parse_quote; + + use super::*; use crate::internals::test_helpers::{ default_cratename, local_insta_assert_debug_snapshot, local_insta_assert_snapshot, pretty_print_syn_str, }; - use super::*; - #[test] fn simple_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: u64, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_struct_with_custom_crate() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: u64, y: String, } - }) - .unwrap(); + }; - let crate_: Path = syn::parse2(quote! { reexporter::borsh }).unwrap(); - let actual = process(&item_struct, crate_).unwrap(); + let crate_: Path = parse_quote! { reexporter::borsh }; - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct.clone(), crate_.clone()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_generics() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { x: HashMap, y: String, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn simple_generic_tuple_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct TupleA(T, u32); - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn bound_generics() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A where V: Value { x: HashMap, y: String, } - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - let actual = process(&item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn recursive_struct() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct CRecC { a: String, b: HashMap, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip1() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G ( #[borsh(skip)] HashMap, U, ); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_tuple_struct_borsh_skip2() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G ( HashMap, #[borsh(skip)] U, ); - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_named_fields_struct_borsh_skip() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct G { #[borsh(skip)] x: HashMap, y: U, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_associated_type() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -219,17 +283,16 @@ mod tests { field: T::Associated, another: V, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct, default_cratename()).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn generic_serialize_bound() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct C { a: String, #[borsh(bound(serialize = @@ -238,17 +301,38 @@ mod tests { ))] b: HashMap, } - }) - .unwrap(); + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn generic_serialize_async_bound() { + let item_struct: ItemStruct = parse_quote! { + struct C { + a: String, + #[borsh(async_bound(serialize = + "T: borsh::ser::BorshSerializeAsync + PartialOrd, + U: borsh::ser::BorshSerializeAsync" + ))] + b: HashMap, + } + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn override_generic_associated_type_wrong_derive() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName { #[borsh(bound(serialize = "::Associated: borsh::ser::BorshSerialize" @@ -256,42 +340,114 @@ mod tests { field: ::Associated, another: V, } - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn async_override_generic_associated_type_wrong_derive() { + let item_struct: ItemStruct = parse_quote! { + struct Parametrized where T: TraitName { + #[borsh(async_bound(serialize = + "::Associated: borsh::ser::BorshSerializeAsync" + ))] + field: ::Associated, + another: V, + } + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn check_serialize_with_attr() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { #[borsh(serialize_with = "third_party_impl::serialize_third_party")] x: ThirdParty, y: u64, } - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } + + #[test] + fn check_serialize_with_async_attr() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(serialize_with_async = "third_party_impl::serialize_third_party")] + x: ThirdParty, + y: u64, + } + }; - let actual = process(&item_struct, default_cratename()).unwrap(); + let actual = process::(item_struct.clone(), default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] fn check_serialize_with_skip_conflict() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct A { - #[borsh(skip,serialize_with = "third_party_impl::serialize_third_party")] + #[borsh(skip, serialize_with = "third_party_impl::serialize_third_party")] x: ThirdParty, y: u64, } - }) - .unwrap(); + }; + + let actual = process::(item_struct.clone(), default_cratename()); + + let err = match actual { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); + + let actual = process::(item_struct, default_cratename()); + + let err = match actual { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); + } + + #[test] + fn check_serialize_with_async_skip_conflict() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(skip, serialize_with_async = "third_party_impl::serialize_third_party")] + x: ThirdParty, + y: u64, + } + }; + + let actual = process::(item_struct.clone(), default_cratename()); + + let err = match actual { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); - let actual = process(&item_struct, default_cratename()); + let actual = process::(item_struct, default_cratename()); let err = match actual { Ok(..) => unreachable!("expecting error here"), diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive-2.snap new file mode 100644 index 000000000..9958fedc1 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive-2.snap @@ -0,0 +1,23 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for Parametrized +where + T: TraitName, + V: borsh::ser::BorshSerializeAsync, + ::Associated: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + <::Associated as borsh::BorshSerializeAsync>::serialize( + &self.field, + writer, + ) + .await?; + ::serialize(&self.another, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive.snap b/borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive.snap new file mode 100644 index 000000000..c6ad3da20 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive.snap @@ -0,0 +1,22 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerialize for Parametrized +where + T: TraitName, + T: borsh::ser::BorshSerialize, + V: borsh::ser::BorshSerialize, +{ + fn serialize<__W: borsh::io::Write>( + &self, + writer: &mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + <::Associated as borsh::BorshSerialize>::serialize( + &self.field, + writer, + )?; + ::serialize(&self.another, writer)?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics-2.snap new file mode 100644 index 000000000..1b4293232 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics-2.snap @@ -0,0 +1,19 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + V: Value, + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + as borsh::BorshSerializeAsync>::serialize(&self.x, writer).await?; + ::serialize(&self.y, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics.snap b/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics.snap index 5c7c6926b..15a8d413d 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -12,8 +12,8 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.x, writer)?; - borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + as borsh::BorshSerialize>::serialize(&self.x, writer)?; + ::serialize(&self.y, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr-2.snap new file mode 100644 index 000000000..bbf2faf4c --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr-2.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + third_party_impl::serialize_third_party(&self.x, writer).await?; + ::serialize(&self.y, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr.snap new file mode 100644 index 000000000..7816a3a1a --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerialize for A +where + K: borsh::ser::BorshSerialize, + V: borsh::ser::BorshSerialize, +{ + fn serialize<__W: borsh::io::Write>( + &self, + writer: &mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + as borsh::BorshSerialize>::serialize(&self.x, writer)?; + ::serialize(&self.y, writer)?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict-2.snap new file mode 100644 index 000000000..3b40ba358 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict-2.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: err +--- +Error( + "`skip` cannot be used at the same time as `serialize_with`, `deserialize_with`, `serialize_with_async` or `deserialize_with_async`", +) diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict.snap new file mode 100644 index 000000000..3b40ba358 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: err +--- +Error( + "`skip` cannot be used at the same time as `serialize_with`, `deserialize_with`, `serialize_with_async` or `deserialize_with_async`", +) diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr-2.snap new file mode 100644 index 000000000..5e5d2dac9 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr-2.snap @@ -0,0 +1,19 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + as borsh::BorshSerializeAsync>::serialize(&self.x, writer) + .await?; + ::serialize(&self.y, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr.snap index 6d977d521..2370ac97c 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -12,7 +12,7 @@ where writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { third_party_impl::serialize_third_party(&self.x, writer)?; - borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::serialize(&self.y, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict-2.snap new file mode 100644 index 000000000..3b40ba358 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict-2.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: err +--- +Error( + "`skip` cannot be used at the same time as `serialize_with`, `deserialize_with`, `serialize_with_async` or `deserialize_with_async`", +) diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict.snap index 0334d44bb..3b40ba358 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict.snap @@ -3,5 +3,5 @@ source: borsh-derive/src/internals/serialize/structs/mod.rs expression: err --- Error( - "`skip` cannot be used at the same time as `serialize_with` or `deserialize_with`", + "`skip` cannot be used at the same time as `serialize_with`, `deserialize_with`, `serialize_with_async` or `deserialize_with_async`", ) diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type.snap index 33b203f80..322493711 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for Parametrized where @@ -12,8 +12,8 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.field, writer)?; - borsh::BorshSerialize::serialize(&self.another, writer)?; - Ok(()) + ::serialize(&self.field, writer)?; + ::serialize(&self.another, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap new file mode 100644 index 000000000..225be6bc6 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap @@ -0,0 +1,16 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for G +where + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.y, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap index 5351f166f..0526e2c5b 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for G where @@ -10,7 +10,7 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::serialize(&self.y, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound-2.snap new file mode 100644 index 000000000..dea73c518 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound-2.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for C +where + T: borsh::ser::BorshSerializeAsync + PartialOrd, + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.a, writer).await?; + as borsh::BorshSerializeAsync>::serialize(&self.b, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound.snap new file mode 100644 index 000000000..b960585ae --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerialize for C +where + T: borsh::ser::BorshSerialize, + U: borsh::ser::BorshSerialize, +{ + fn serialize<__W: borsh::io::Write>( + &self, + writer: &mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.a, writer)?; + as borsh::BorshSerialize>::serialize(&self.b, writer)?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound-2.snap new file mode 100644 index 000000000..62754e200 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound-2.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for C +where + T: borsh::ser::BorshSerializeAsync, + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.a, writer).await?; + as borsh::BorshSerializeAsync>::serialize(&self.b, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound.snap index c0309d69a..ad8e7908a 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for C where @@ -11,8 +11,8 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.a, writer)?; - borsh::BorshSerialize::serialize(&self.b, writer)?; - Ok(()) + ::serialize(&self.a, writer)?; + as borsh::BorshSerialize>::serialize(&self.b, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap new file mode 100644 index 000000000..56479f61c --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap @@ -0,0 +1,16 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for G +where + U: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.1, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap index 447fcb32e..2ba771ccb 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for G where @@ -10,7 +10,7 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.1, writer)?; - Ok(()) + ::serialize(&self.1, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap new file mode 100644 index 000000000..1ff89c2d7 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap @@ -0,0 +1,17 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for G +where + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + as borsh::BorshSerializeAsync>::serialize(&self.0, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap index 8c5800a25..59b43cd7f 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for G where @@ -11,7 +11,7 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.0, writer)?; - Ok(()) + as borsh::BorshSerialize>::serialize(&self.0, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive-2.snap new file mode 100644 index 000000000..568115c56 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive-2.snap @@ -0,0 +1,23 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for Parametrized +where + T: TraitName, + T: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + <::Associated as borsh::BorshSerializeAsync>::serialize( + &self.field, + writer, + ) + .await?; + ::serialize(&self.another, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive.snap b/borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive.snap index 9b2bf20b3..c7bd3fd42 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for Parametrized where @@ -12,8 +12,11 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.field, writer)?; - borsh::BorshSerialize::serialize(&self.another, writer)?; - Ok(()) + <::Associated as borsh::BorshSerialize>::serialize( + &self.field, + writer, + )?; + ::serialize(&self.another, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct-2.snap new file mode 100644 index 000000000..6f25d5914 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct-2.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for CRecC { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.a, writer).await?; + as borsh::BorshSerializeAsync>::serialize(&self.b, writer) + .await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct.snap b/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct.snap index 510b71b77..33be64902 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct.snap @@ -1,14 +1,14 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for CRecC { fn serialize<__W: borsh::io::Write>( &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.a, writer)?; - borsh::BorshSerialize::serialize(&self.b, writer)?; - Ok(()) + ::serialize(&self.a, writer)?; + as borsh::BorshSerialize>::serialize(&self.b, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct-2.snap new file mode 100644 index 000000000..a94669553 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct-2.snap @@ -0,0 +1,17 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for TupleA +where + T: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.0, writer).await?; + ::serialize(&self.1, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct.snap index 984defae9..7486c2358 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for TupleA where @@ -10,8 +10,8 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.0, writer)?; - borsh::BorshSerialize::serialize(&self.1, writer)?; - Ok(()) + ::serialize(&self.0, writer)?; + ::serialize(&self.1, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics-2.snap new file mode 100644 index 000000000..299dcfd67 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics-2.snap @@ -0,0 +1,18 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A +where + K: borsh::ser::BorshSerializeAsync, + V: borsh::ser::BorshSerializeAsync, +{ + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + as borsh::BorshSerializeAsync>::serialize(&self.x, writer).await?; + ::serialize(&self.y, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics.snap index 3518ba3a4..47667b80d 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics.snap @@ -1,6 +1,6 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A where @@ -11,8 +11,8 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.x, writer)?; - borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + as borsh::BorshSerialize>::serialize(&self.x, writer)?; + ::serialize(&self.y, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct-2.snap new file mode 100644 index 000000000..5e9b3b15e --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct-2.snap @@ -0,0 +1,14 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl borsh::ser::BorshSerializeAsync for A { + async fn serialize<'async_variant, __W: borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), borsh::io::Error> { + ::serialize(&self.x, writer).await?; + ::serialize(&self.y, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct.snap index 8904dca85..eac613281 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct.snap @@ -1,14 +1,14 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl borsh::ser::BorshSerialize for A { fn serialize<__W: borsh::io::Write>( &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.x, writer)?; - borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::serialize(&self.x, writer)?; + ::serialize(&self.y, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate-2.snap new file mode 100644 index 000000000..8361c83c3 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate-2.snap @@ -0,0 +1,16 @@ +--- +source: borsh-derive/src/internals/serialize/structs/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +impl reexporter::borsh::ser::BorshSerializeAsync for A { + async fn serialize<'async_variant, __W: reexporter::borsh::async_io::AsyncWrite>( + &'async_variant self, + writer: &'async_variant mut __W, + ) -> ::core::result::Result<(), reexporter::borsh::io::Error> { + ::serialize(&self.x, writer) + .await?; + ::serialize(&self.y, writer) + .await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate.snap b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate.snap index bd331f30d..462572e22 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate.snap @@ -1,14 +1,14 @@ --- source: borsh-derive/src/internals/serialize/structs/mod.rs -expression: pretty_print_syn_str(&actual).unwrap() +expression: pretty_print_syn_str(actual).unwrap() --- impl reexporter::borsh::ser::BorshSerialize for A { fn serialize<__W: reexporter::borsh::io::Write>( &self, writer: &mut __W, ) -> ::core::result::Result<(), reexporter::borsh::io::Error> { - reexporter::borsh::BorshSerialize::serialize(&self.x, writer)?; - reexporter::borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::serialize(&self.x, writer)?; + ::serialize(&self.y, writer)?; + ::core::result::Result::Ok(()) } } diff --git a/borsh-derive/src/internals/serialize/unions/mod.rs b/borsh-derive/src/internals/serialize/unions/mod.rs index 3806821bd..89200b4ea 100644 --- a/borsh-derive/src/internals/serialize/unions/mod.rs +++ b/borsh-derive/src/internals/serialize/unions/mod.rs @@ -1,6 +1,9 @@ use proc_macro2::TokenStream as TokenStream2; use syn::{ItemUnion, Path}; -pub fn process(_input: &ItemUnion, _cratename: Path) -> syn::Result { +pub fn process( + _input: ItemUnion, + _cratename: Path, +) -> syn::Result { unimplemented!() } diff --git a/borsh-derive/src/internals/test_helpers.rs b/borsh-derive/src/internals/test_helpers.rs index 806b7c826..a4ce8ae4a 100644 --- a/borsh-derive/src/internals/test_helpers.rs +++ b/borsh-derive/src/internals/test_helpers.rs @@ -1,37 +1,36 @@ -use super::cratename::BORSH; -use proc_macro2::Span; -use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; -use std::fmt::Write; +use proc_macro2::{Span, TokenStream}; +use quote::ToTokens; use syn::{Ident, Path}; -pub fn pretty_print_syn_str(input: &TokenStream) -> syn::Result { - let input = format!("{}", quote!(#input)); - let syn_file = syn::parse_str::(&input)?; +use super::cratename::BORSH; + +pub fn pretty_print_syn_str(input: TokenStream) -> syn::Result { + let syn_file = syn::parse2::(input)?; Ok(prettyplease::unparse(&syn_file)) } pub fn debug_print_vec_of_tokenizable(optional: Option>) -> String { - let mut s = String::new(); if let Some(vec) = optional { + let mut s = String::new(); for element in vec { - writeln!(&mut s, "{}", element.to_token_stream()).unwrap(); + s.push_str(&element.to_token_stream().to_string()); + s.push('\n'); } + s } else { - write!(&mut s, "None").unwrap(); + "None".to_owned() } - s } pub fn debug_print_tokenizable(optional: Option) -> String { - let mut s = String::new(); if let Some(type_) = optional { - writeln!(&mut s, "{}", type_.to_token_stream()).unwrap(); + let mut s = type_.to_token_stream().to_string(); + s.push('\n'); + s } else { - write!(&mut s, "None").unwrap(); + "None".to_owned() } - s } macro_rules! local_insta_assert_debug_snapshot { @@ -57,4 +56,5 @@ pub(crate) fn default_cratename() -> Path { cratename.into() } -pub(crate) use {local_insta_assert_debug_snapshot, local_insta_assert_snapshot}; +pub(crate) use local_insta_assert_debug_snapshot; +pub(crate) use local_insta_assert_snapshot; diff --git a/borsh-derive/src/lib.rs b/borsh-derive/src/lib.rs index 4cc91cfa3..6f6ae501c 100644 --- a/borsh-derive/src/lib.rs +++ b/borsh-derive/src/lib.rs @@ -14,12 +14,12 @@ use syn::{DeriveInput, Error, ItemEnum, ItemStruct, ItemUnion, Path}; /// by convention, local to borsh-derive crate, imports from proc_macro (1) are not allowed in `internals` module or in any of its submodules. mod internals; -use crate::internals::attributes::item; - #[cfg(feature = "schema")] use internals::schema; use internals::{cratename, deserialize, serialize}; +use crate::internals::attributes::item; + fn check_attrs_get_cratename(input: &TokenStream) -> Result { let input = input.clone(); @@ -35,6 +35,18 @@ fn check_attrs_get_cratename(input: &TokenStream) -> Result { /// moved to docs of **Derive Macro** `BorshSerialize` in `borsh` crate #[proc_macro_derive(BorshSerialize, attributes(borsh))] pub fn borsh_serialize(input: TokenStream) -> TokenStream { + borsh_serialize_generic::(input) +} + +/// --- +/// +/// moved to docs of **Derive Macro** `BorshSerializeAsync` in `borsh` crate +#[proc_macro_derive(BorshSerializeAsync, attributes(borsh))] +pub fn borsh_serialize_async(input: TokenStream) -> TokenStream { + borsh_serialize_generic::(input) +} + +fn borsh_serialize_generic(input: TokenStream) -> TokenStream { let cratename = match check_attrs_get_cratename(&input) { Ok(cratename) => cratename, Err(err) => { @@ -43,11 +55,11 @@ pub fn borsh_serialize(input: TokenStream) -> TokenStream { }; let res = if let Ok(input) = syn::parse::(input.clone()) { - serialize::structs::process(&input, cratename) + serialize::structs::process::(input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - serialize::enums::process(&input, cratename) + serialize::enums::process::(input, cratename) } else if let Ok(input) = syn::parse::(input) { - serialize::unions::process(&input, cratename) + serialize::unions::process::(input, cratename) } else { // Derive macros can only be defined on structs, enums, and unions. unreachable!() @@ -60,6 +72,18 @@ pub fn borsh_serialize(input: TokenStream) -> TokenStream { /// moved to docs of **Derive Macro** `BorshDeserialize` in `borsh` crate #[proc_macro_derive(BorshDeserialize, attributes(borsh))] pub fn borsh_deserialize(input: TokenStream) -> TokenStream { + borsh_deserialize_generic::(input) +} + +/// --- +/// +/// moved to docs of **Derive Macro** `BorshDeserializeAsync` in `borsh` crate +#[proc_macro_derive(BorshDeserializeAsync, attributes(borsh))] +pub fn borsh_deserialize_async(input: TokenStream) -> TokenStream { + borsh_deserialize_generic::(input) +} + +fn borsh_deserialize_generic(input: TokenStream) -> TokenStream { let cratename = match check_attrs_get_cratename(&input) { Ok(cratename) => cratename, Err(err) => { @@ -68,11 +92,11 @@ pub fn borsh_deserialize(input: TokenStream) -> TokenStream { }; let res = if let Ok(input) = syn::parse::(input.clone()) { - deserialize::structs::process(&input, cratename) + deserialize::structs::process::(input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - deserialize::enums::process(&input, cratename) + deserialize::enums::process::(input, cratename) } else if let Ok(input) = syn::parse::(input) { - deserialize::unions::process(&input, cratename) + deserialize::unions::process::(input, cratename) } else { // Derive macros can only be defined on structs, enums, and unions. unreachable!() @@ -94,9 +118,9 @@ pub fn borsh_schema(input: TokenStream) -> TokenStream { }; let res = if let Ok(input) = syn::parse::(input.clone()) { - schema::structs::process(&input, cratename) + schema::structs::process(input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - schema::enums::process(&input, cratename) + schema::enums::process(input, cratename) } else if syn::parse::(input).is_ok() { Err(Error::new( Span::call_site(), diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index eaed26a65..2d702fa96 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -211,7 +211,7 @@ pub trait EnumExtAsync: BorshDeserializeAsync { /// /// # #[cfg(feature = "derive")] /// impl borsh::de::BorshDeserializeAsync for OneOrZero { - /// async fn deserialize_reader( + /// async fn deserialize_reader( /// reader: &mut R, /// ) -> borsh::io::Result { /// use borsh::de::EnumExtAsync; @@ -227,18 +227,18 @@ pub trait EnumExtAsync: BorshDeserializeAsync { /// } /// } /// - /// use borsh::from_slice; + /// use borsh::from_reader_async; /// let data = b"\0"; - /// # #[cfg(feature = "derive")] - /// assert_eq!(MyEnum::Zero, from_slice::(&data[..]).unwrap()); - /// # #[cfg(feature = "derive")] - /// assert_eq!(MyEnum::Zero, from_slice::(&data[..]).unwrap().0); + /// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] + /// assert_eq!(MyEnum::Zero, from_reader_async::<_, MyEnum>(&mut &data[..]).await.unwrap()); + /// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] + /// assert_eq!(MyEnum::Zero, from_reader_async::<_, OneOrZero>(&mut &data[..]).await.unwrap().0); /// /// let data = b"\x02\0\0\0\0"; - /// # #[cfg(feature = "derive")] - /// assert_eq!(MyEnum::Many(Vec::new()), from_slice::(&data[..]).unwrap()); - /// # #[cfg(feature = "derive")] - /// assert!(from_slice::(&data[..]).is_err()); + /// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] + /// assert_eq!(MyEnum::Many(Vec::new()), from_reader_async::<_, MyEnum>(&mut &data[..]).await.unwrap()); + /// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] + /// assert!(from_reader_async::<_, OneOrZero>(&mut &data[..]).await.is_err()); /// # }); /// ``` fn deserialize_variant( diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index 24b0c6d53..18a4250a1 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -7,12 +7,18 @@ extern crate alloc; #[doc = include_str!("../docs/rustdoc_include/borsh_deserialize.md")] #[cfg(feature = "derive")] pub use borsh_derive::BorshDeserialize; +// TODO: add docs +#[cfg(all(feature = "derive", feature = "unstable__async"))] +pub use borsh_derive::BorshDeserializeAsync; #[doc = include_str!("../docs/rustdoc_include/borsh_schema.md")] #[cfg(feature = "unstable__schema")] pub use borsh_derive::BorshSchema; #[doc = include_str!("../docs/rustdoc_include/borsh_serialize.md")] #[cfg(feature = "derive")] pub use borsh_derive::BorshSerialize; +// TODO: add docs +#[cfg(all(feature = "derive", feature = "unstable__async"))] +pub use borsh_derive::BorshSerializeAsync; pub mod de; diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 88de04370..72818a58f 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -73,6 +73,12 @@ pub trait BorshSerialize { /// ``` /// # tokio_test::block_on(async { /// use borsh::BorshSerializeAsync; +/// # #[cfg(all(feature = "derive", feature = "unstable__tokio"))] +/// # use std::io; +/// # #[cfg(all(feature = "derive", feature = "unstable__async-std"))] +/// # use async_std::io; +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] +/// use io::Cursor; /// /// /// derive is only available if borsh is built with `features = ["derive"]` /// # #[cfg(feature = "derive")] @@ -84,22 +90,22 @@ pub trait BorshSerialize { /// # #[cfg(feature = "derive")] /// let x = MyBorshSerializableStruct { value: "hello".to_owned() }; /// let mut buffer: Vec = Vec::new(); -/// # #[cfg(feature = "derive")] +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] /// x.serialize(&mut buffer).await.unwrap(); -/// # #[cfg(feature = "derive")] +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] /// let single_serialized_buffer_len = buffer.len(); /// -/// # #[cfg(feature = "derive")] +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] /// x.serialize(&mut buffer).await.unwrap(); -/// # #[cfg(feature = "derive")] +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] /// assert_eq!(buffer.len(), single_serialized_buffer_len * 2); /// -/// # #[cfg(feature = "derive")] -/// let mut buffer: Vec = vec![0; 1024 + single_serialized_buffer_len]; -/// # #[cfg(feature = "derive")] -/// let mut buffer_slice_enough_for_the_data = &mut buffer[1024..1024 + single_serialized_buffer_len]; -/// # #[cfg(feature = "derive")] -/// x.serialize(&mut buffer_slice_enough_for_the_data).await.unwrap(); +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] +/// let mut buffer: Cursor> = Cursor::new(vec![0; 1024 + single_serialized_buffer_len]); +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] +/// buffer.set_position(1024); +/// # #[cfg(all(feature = "derive", any(feature = "unstable__tokio", feature = "unstable__async-std")))] +/// x.serialize(&mut buffer).await.unwrap(); /// # }) /// ``` #[cfg(feature = "unstable__async")] diff --git a/borsh/tests/compile_derives/async_derives/test_generic_enums.rs b/borsh/tests/compile_derives/async_derives/test_generic_enums.rs new file mode 100644 index 000000000..854cbe343 --- /dev/null +++ b/borsh/tests/compile_derives/async_derives/test_generic_enums.rs @@ -0,0 +1,47 @@ +use alloc::collections::BTreeMap; +#[allow(unused)] +use alloc::{string::String, vec::Vec}; +#[cfg(hash_collections)] +use core::{cmp::Eq, hash::Hash}; +#[cfg(feature = "std")] +use std::collections::HashMap; + +use borsh::{BorshDeserializeAsync, BorshSerializeAsync}; +#[cfg(feature = "hashbrown")] +use hashbrown::HashMap; + +/// `T: Ord` bound is required for `BorshDeserialize` derive to be successful +#[derive(BorshSerializeAsync, BorshDeserializeAsync, PartialEq, Debug)] +enum E { + X { f: BTreeMap }, + Y(W), +} + +#[cfg(hash_collections)] +#[derive(BorshSerializeAsync, BorshDeserializeAsync, Debug)] +enum I1 { + B { + #[allow(unused)] + #[borsh(skip, async_bound(serialize = "V: Sync", deserialize = "V: Send"))] + x: HashMap, + y: String, + }, + C(K, Vec), +} + +#[cfg(hash_collections)] +#[derive(BorshSerializeAsync, BorshDeserializeAsync, Debug)] +enum I2 { + B { + x: HashMap, + y: String, + }, + C( + K, + #[borsh( + skip, + async_bound(serialize = "U: Sync", deserialize = "U: Default + Send") + )] + U, + ), +} diff --git a/borsh/tests/compile_derives/async_derives/test_generic_structs.rs b/borsh/tests/compile_derives/async_derives/test_generic_structs.rs new file mode 100644 index 000000000..e69de29bb diff --git a/borsh/tests/compile_derives/async_derives/test_macro_namespace_collisions.rs b/borsh/tests/compile_derives/async_derives/test_macro_namespace_collisions.rs new file mode 100644 index 000000000..121966ff5 --- /dev/null +++ b/borsh/tests/compile_derives/async_derives/test_macro_namespace_collisions.rs @@ -0,0 +1,21 @@ +// Borsh macros should not collide with the local modules: +// https://github.com/near/borsh-rs/issues/11 +mod std {} +mod core {} + +#[derive(borsh::BorshSerializeAsync, borsh::BorshDeserializeAsync)] +struct A; + +#[derive(borsh::BorshSerializeAsync, borsh::BorshDeserializeAsync)] +enum B { + C, + D, +} + +#[derive(borsh::BorshSerializeAsync, borsh::BorshDeserializeAsync)] +struct C { + x: u64, + #[allow(unused)] + #[borsh(skip)] + y: u64, +} diff --git a/borsh/tests/compile_derives/async_derives/test_recursive_structs.rs b/borsh/tests/compile_derives/async_derives/test_recursive_structs.rs new file mode 100644 index 000000000..e69de29bb diff --git a/borsh/tests/tests.rs b/borsh/tests/tests.rs index ea8cad5d4..e82d7e98b 100644 --- a/borsh/tests/tests.rs +++ b/borsh/tests/tests.rs @@ -22,6 +22,14 @@ mod compile_derives { mod test_generic_enums; mod test_recursive_structs; + #[cfg(feature = "unstable__async")] + mod async_derives { + mod test_generic_structs; + mod test_generic_enums; + mod test_recursive_structs; + mod test_macro_namespace_collisions; + } + #[cfg(feature = "unstable__schema")] mod schema { mod test_generic_enums;