From d4d92f7f162678e305f0073f39f5cb472fa4acf2 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 21 Jan 2025 14:46:10 +0200 Subject: [PATCH 01/69] WIP: implement support for async I/O. FIXME: resolve issue with type parameters needing `Send` bound --- Cargo.toml | 3 +- benchmarks/Cargo.toml | 2 +- borsh-derive/Cargo.toml | 10 +- borsh-derive/src/lib.rs | 17 +- borsh/Cargo.toml | 10 +- borsh/src/de/mod.rs | 765 +++++++++++++++++++++++++++++++++------- borsh/src/lib.rs | 3 + rustfmt.toml | 4 + 8 files changed, 658 insertions(+), 156 deletions(-) create mode 100644 rustfmt.toml diff --git a/Cargo.toml b/Cargo.toml index a02fd6d48..25d40eeea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ members = ["borsh", "borsh-derive", "fuzz/fuzz-run", "benchmarks"] [workspace.package] # shared version of all public crates in the workspace version = "1.5.4" -rust-version = "1.67.0" +edition = "2018" +rust-version = "1.70.0" diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index aad6202b9..c8d23aac1 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -3,7 +3,7 @@ name = "benchmarks" version.workspace = true rust-version.workspace = true authors = ["Near Inc "] -edition = "2018" +edition.workspace = true publish = false # This is somehow needed for command line arguments to work: https://github.com/bheisler/criterion.rs/issues/193#issuecomment-415740713 diff --git a/borsh-derive/Cargo.toml b/borsh-derive/Cargo.toml index 0bfa2ed8f..c0200bc07 100644 --- a/borsh-derive/Cargo.toml +++ b/borsh-derive/Cargo.toml @@ -3,7 +3,7 @@ name = "borsh-derive" version.workspace = true rust-version.workspace = true authors = ["Near Inc "] -edition = "2018" +edition.workspace = true license = "Apache-2.0" readme = "README.md" categories = ["encoding", "network-programming"] @@ -18,14 +18,14 @@ exclude = ["*.snap"] proc-macro = true [dependencies] -syn = { version = "2.0.81", features = ["full", "fold"] } +syn = { version = "2.0", features = ["full", "fold"] } proc-macro-crate = "3" -proc-macro2 = "1" -quote = "1" +proc-macro2 = "1.0" +quote = "1.0" once_cell = "1.18.0" [dev-dependencies] -syn = { version = "2.0.81", features = ["full", "fold", "parsing"] } +syn = { version = "2.0", features = ["parsing"] } prettyplease = "0.2.9" insta = "1.29.0" diff --git a/borsh-derive/src/lib.rs b/borsh-derive/src/lib.rs index f12dd3992..4cc91cfa3 100644 --- a/borsh-derive/src/lib.rs +++ b/borsh-derive/src/lib.rs @@ -52,10 +52,7 @@ pub fn borsh_serialize(input: TokenStream) -> TokenStream { // Derive macros can only be defined on structs, enums, and unions. unreachable!() }; - TokenStream::from(match res { - Ok(res) => res, - Err(err) => err.to_compile_error(), - }) + TokenStream::from(res.unwrap_or_else(|err| err.to_compile_error())) } /// --- @@ -80,10 +77,7 @@ pub fn borsh_deserialize(input: TokenStream) -> TokenStream { // Derive macros can only be defined on structs, enums, and unions. unreachable!() }; - TokenStream::from(match res { - Ok(res) => res, - Err(err) => err.to_compile_error(), - }) + TokenStream::from(res.unwrap_or_else(|err| err.to_compile_error())) } /// --- @@ -104,7 +98,7 @@ pub fn borsh_schema(input: TokenStream) -> TokenStream { } else if let Ok(input) = syn::parse::(input.clone()) { schema::enums::process(&input, cratename) } else if syn::parse::(input).is_ok() { - Err(syn::Error::new( + Err(Error::new( Span::call_site(), "Borsh schema does not support unions yet.", )) @@ -112,8 +106,5 @@ pub fn borsh_schema(input: TokenStream) -> TokenStream { // Derive macros can only be defined on structs, enums, and unions. unreachable!() }; - TokenStream::from(match res { - Ok(res) => res, - Err(err) => err.to_compile_error(), - }) + TokenStream::from(res.unwrap_or_else(|err| err.to_compile_error())) } diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index b1f3cb211..b13aa9ea2 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -3,7 +3,7 @@ name = "borsh" version.workspace = true rust-version.workspace = true authors = ["Near Inc "] -edition = "2018" +edition.workspace = true license = "MIT OR Apache-2.0" readme = "README.md" categories = ["encoding", "network-programming"] @@ -41,6 +41,11 @@ hashbrown = { version = ">=0.11,<0.15.0", optional = true } bytes = { version = "1", optional = true } bson = { version = "2", optional = true } +async-generic = { git = "https://github.com/DanikVitek/async-generic.git", version = "2.0" } +async-trait = { version = "0.1", optional = true } +tokio = { version = "1", features = ["io-util"], optional = true } +async-std = { version = "1", features = ["async-io"], optional = true } + [dev-dependencies] insta = "1.29.0" serde_json = { version = "1" } @@ -52,6 +57,9 @@ targets = ["x86_64-unknown-linux-gnu"] [features] default = ["std"] derive = ["borsh-derive"] +async = ["dep:async-trait"] +tokio = ["async", "dep:tokio"] +async-std = ["async", "dep:async-std"] unstable__schema = ["derive", "borsh-derive/schema"] std = [] # Opt into impls for Rc and Arc. Serializing and deserializing these types diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 0abb36e3e..401f3b499 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1,25 +1,28 @@ -use core::marker::PhantomData; -use core::mem::MaybeUninit; use core::{ convert::{TryFrom, TryInto}, - mem::size_of, + marker::PhantomData, + mem::{size_of, MaybeUninit}, }; +use async_generic::async_generic; +#[cfg(feature = "async")] +use async_trait::async_trait; #[cfg(feature = "bytes")] use bytes::{BufMut, BytesMut}; -use crate::__private::maybestd::{ - borrow::{Borrow, Cow, ToOwned}, - boxed::Box, - collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, - format, - string::{String, ToString}, - vec, - vec::Vec, +use crate::{ + __private::maybestd::{ + borrow::{Borrow, Cow, ToOwned}, + boxed::Box, + collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, + format, + string::{String, ToString}, + vec, + vec::Vec, + }, + error::check_zst, + io::{Error, ErrorKind, Read, Result}, }; -use crate::io::{Error, ErrorKind, Read, Result}; - -use crate::error::check_zst; mod hint; @@ -33,6 +36,7 @@ const ERROR_INVALID_ZERO_VALUE: &str = "Expected a non-zero value"; const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order"; /// A data-structure that can be de-serialized from binary format by NBOR. +#[async_generic(cfg_attr(feature = "async", async_trait))] pub trait BorshDeserialize: Sized { /// Deserializes this instance from a given slice of bytes. /// Updates the buffer to point at the remaining bytes. @@ -40,6 +44,10 @@ pub trait BorshDeserialize: Sized { Self::deserialize_reader(&mut *buf) } + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result where Self: Send + )] fn deserialize_reader(reader: &mut R) -> Result; /// Deserialize this instance from a slice of bytes. @@ -52,10 +60,20 @@ pub trait BorshDeserialize: Sized { Ok(result) } + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result where Result: Send + )] fn try_from_reader(reader: &mut R) -> Result { - let result = Self::deserialize_reader(reader)?; + let result = if _sync { + Self::deserialize_reader(reader) + } else { + Self::deserialize_reader_async(reader).await + }?; let mut buf = [0u8; 1]; - match reader.read_exact(&mut buf) { + + let res = reader.read_exact(&mut buf); + match if _sync { res } else { res.await } { Err(f) if f.kind() == ErrorKind::UnexpectedEof => Ok(result), _ => Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)), } @@ -63,6 +81,12 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] + #[async_generic( + #[cfg(feature = "async")] + async_signature(len: u32, reader: &mut R) -> Result>> + where + Self: Send + )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let _ = len; let _ = reader; @@ -71,12 +95,52 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result> + where + Self: Send + )] fn array_from_reader(reader: &mut R) -> Result> { let _ = reader; Ok(None) } } +#[cfg(feature = "async")] +#[async_trait] +pub trait AsyncRead: Unpin + Send { + async fn read(&mut self, buf: &mut [u8]) -> Result; + + async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>; +} + +#[cfg(feature = "tokio")] +#[async_trait] +impl AsyncRead for R { + async fn read(&mut self, buf: &mut [u8]) -> Result { + tokio::io::AsyncReadExt::read(self, buf).await + } + + async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { + tokio::io::AsyncReadExt::read_exact(self, buf) + .await + .map(|_| ()) + } +} + +#[cfg(feature = "async-std")] +#[async_trait] +impl AsyncRead for R { + async fn read(&mut self, buf: &mut [u8]) -> Result { + async_std::io::ReadExt::read(self, buf).await + } + + async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { + async_std::io::ReadExt::read_exact(self, buf).await + } +} + /// Additional methods offered on enums which is used by `[derive(BorshDeserialize)]`. pub trait EnumExt: BorshDeserialize { /// Deserialises given variant of an enum from the reader. @@ -143,18 +207,27 @@ fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for u8 { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 1]; - reader - .read_exact(&mut buf) + let result = reader.read_exact(&mut buf); + if _async { result.await } else { result } .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(buf[0]) } #[inline] #[doc(hidden)] + #[async_generic( + #[cfg(feature = "async")] + async_signature(len: u32, reader: &mut R) -> Result>> where Self: Send + )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let len: usize = len.try_into().map_err(|_| ErrorKind::InvalidData)?; // Avoid OOM by limiting the size of allocation. This makes the read @@ -168,7 +241,10 @@ impl BorshDeserialize for u8 { vec.resize(vec.len().saturating_mul(2).min(len), 0) } // TODO(mina86): Convert this to read_buf once that stabilises. - match reader.read(&mut vec.as_mut_slice()[pos..])? { + match { + let res = reader.read(&mut vec.as_mut_slice()[pos..]); + if _sync { res } else { res.await }? + } { 0 => { return Err(Error::new( ErrorKind::InvalidData, @@ -185,10 +261,14 @@ impl BorshDeserialize for u8 { #[inline] #[doc(hidden)] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result> + )] fn array_from_reader(reader: &mut R) -> Result> { let mut arr = [0u8; N]; - reader - .read_exact(&mut arr) + let res = reader.read_exact(&mut arr); + if _sync { res } else { res.await } .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(Some(arr)) } @@ -196,12 +276,17 @@ impl BorshDeserialize for u8 { macro_rules! impl_for_integer { ($type: ident) => { + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for $type { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; size_of::<$type>()]; - reader - .read_exact(&mut buf) + let res = reader.read_exact(&mut buf); + if _sync { res } else { res.await } .map_err(unexpected_eof_to_unexpected_length_of_input)?; let res = $type::from_le_bytes(buf.try_into().unwrap()); Ok(res) @@ -222,11 +307,22 @@ impl_for_integer!(u128); macro_rules! impl_for_nonzero_integer { ($type: ty) => { + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for $type { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - <$type>::new(BorshDeserialize::deserialize_reader(reader)?) - .ok_or_else(|| Error::new(ErrorKind::InvalidData, ERROR_INVALID_ZERO_VALUE)) + <$type>::new( + if _sync { + BorshDeserialize::deserialize_reader(reader) + } else { + BorshDeserialize::deserialize_reader_async(reader).await + }? + ) + .ok_or_else(|| Error::new(ErrorKind::InvalidData, ERROR_INVALID_ZERO_VALUE)) } } }; @@ -244,42 +340,47 @@ impl_for_nonzero_integer!(core::num::NonZeroU64); impl_for_nonzero_integer!(core::num::NonZeroU128); impl_for_nonzero_integer!(core::num::NonZeroUsize); -impl BorshDeserialize for isize { - fn deserialize_reader(reader: &mut R) -> Result { - let i: i64 = BorshDeserialize::deserialize_reader(reader)?; - let i = isize::try_from(i).map_err(|_| { - Error::new( - ErrorKind::InvalidData, - ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_ISIZE, - ) - })?; - Ok(i) - } +macro_rules! impl_for_size_integer { + ($type: ty: $temp_type: ty, $msg: expr) => { + #[async_generic(cfg_attr(feature = "async", async_trait))] + impl BorshDeserialize for $type { + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] + fn deserialize_reader(reader: &mut R) -> Result { + let i: $temp_type = if _sync { + BorshDeserialize::deserialize_reader(reader) + } else { + BorshDeserialize::deserialize_reader_async(reader).await + }?; + let i = <$type>::try_from(i).map_err(|_| { + Error::new(ErrorKind::InvalidData, $msg) + })?; + Ok(i) + } + } + }; } -impl BorshDeserialize for usize { - fn deserialize_reader(reader: &mut R) -> Result { - let u: u64 = BorshDeserialize::deserialize_reader(reader)?; - let u = usize::try_from(u).map_err(|_| { - Error::new( - ErrorKind::InvalidData, - ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE, - ) - })?; - Ok(u) - } -} +impl_for_size_integer!(isize: i64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_ISIZE); +impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, -// and vice-versa. We disallow NaNs to avoid this issue. +// and vice versa. We disallow NaNs to avoid this issue. macro_rules! impl_for_float { ($type: ident, $int_type: ident) => { + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for $type { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; size_of::<$type>()]; - reader - .read_exact(&mut buf) + let res = reader.read_exact(&mut buf); + if _sync { res } else { res.await } .map_err(unexpected_eof_to_unexpected_length_of_input)?; let res = $type::from_bits($int_type::from_le_bytes(buf.try_into().unwrap())); if res.is_nan() { @@ -297,10 +398,19 @@ macro_rules! impl_for_float { impl_for_float!(f32, u32); impl_for_float!(f64, u64); +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for bool { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let b: u8 = BorshDeserialize::deserialize_reader(reader)?; + let b: u8 = if _sync { + BorshDeserialize::deserialize_reader(reader) + } else { + BorshDeserialize::deserialize_reader_async(reader).await + }?; if b == 0 { Ok(false) } else if b == 1 { @@ -313,55 +423,95 @@ impl BorshDeserialize for bool { } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for Option where T: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let flag: u8 = BorshDeserialize::deserialize_reader(reader)?; - if flag == 0 { - Ok(None) - } else if flag == 1 { - Ok(Some(T::deserialize_reader(reader)?)) + let flag: u8 = if _sync { + BorshDeserialize::deserialize_reader(reader) } else { - let msg = format!( - "Invalid Option representation: {}. The first byte must be 0 or 1", - flag - ); - - Err(Error::new(ErrorKind::InvalidData, msg)) + BorshDeserialize::deserialize_reader_async(reader).await + }?; + match flag { + 0 => Ok(None), + 1 => Ok(Some(if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader_async(reader).await + }?)), + _ => { + let msg = format!( + "Invalid Option representation: {}. The first byte must be 0 or 1", + flag + ); + + Err(Error::new(ErrorKind::InvalidData, msg)) + } } } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for core::result::Result where T: BorshDeserialize, E: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let flag: u8 = BorshDeserialize::deserialize_reader(reader)?; - if flag == 0 { - Ok(Err(E::deserialize_reader(reader)?)) - } else if flag == 1 { - Ok(Ok(T::deserialize_reader(reader)?)) + let flag: u8 = if _sync { + BorshDeserialize::deserialize_reader(reader) } else { - let msg = format!( - "Invalid Result representation: {}. The first byte must be 0 or 1", - flag - ); - - Err(Error::new(ErrorKind::InvalidData, msg)) + BorshDeserialize::deserialize_reader_async(reader).await + }?; + match flag { + 0 => Ok(Err(if _sync { + E::deserialize_reader(reader) + } else { + E::deserialize_reader_async(reader).await + }?)), + 1 => Ok(Ok(if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader_async(reader).await + }?)), + _ => { + let msg = format!( + "Invalid Result representation: {}. The first byte must be 0 or 1", + flag + ); + + Err(Error::new(ErrorKind::InvalidData, msg)) + } } } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for String { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - String::from_utf8(Vec::::deserialize_reader(reader)?).map_err(|err| { + String::from_utf8(if _sync { + Vec::::deserialize_reader(reader) + } else { + Vec::::deserialize_reader_async(reader).await + }?) + .map_err(|err| { let msg = err.to_string(); Error::new(ErrorKind::InvalidData, msg) }) @@ -374,47 +524,91 @@ pub mod ascii { //! //! Module defines [BorshDeserialize] implementation for //! some types from [ascii](::ascii) crate. - use crate::BorshDeserialize; - use crate::__private::maybestd::{string::ToString, vec::Vec}; - use crate::io::{Error, ErrorKind, Read, Result}; + use async_generic::async_generic; + #[cfg(feature = "async")] + use async_trait::async_trait; + + #[cfg(feature = "async")] + use super::AsyncRead; + use crate::{ + BorshDeserialize, + __private::maybestd::{string::ToString, vec::Vec}, + io::{Error, ErrorKind, Read, Result}, + }; + + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for ascii::AsciiString { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let bytes = Vec::::deserialize_reader(reader)?; + let bytes = if _sync { + Vec::::deserialize_reader(reader) + } else { + Vec::::deserialize_reader_async(reader).await + }?; ascii::AsciiString::from_ascii(bytes) .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())) } } + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for ascii::AsciiChar { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let byte = u8::deserialize_reader(reader)?; + let byte = if _sync { + u8::deserialize_reader(reader) + } else { + u8::deserialize_reader_async(reader).await + }?; ascii::AsciiChar::from_ascii(byte) .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())) } } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for Vec where T: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; - let len = u32::deserialize_reader(reader)?; + let len = if _sync { + u32::deserialize_reader(reader) + } else { + u32::deserialize_reader_async(reader).await + }?; if len == 0 { Ok(Vec::new()) - } else if let Some(vec_bytes) = T::vec_from_reader(len, reader)? { + } else if let Some(vec_bytes) = if _sync { + T::vec_from_reader(len, reader) + } else { + T::vec_from_reader_async(len, reader).await + }? { Ok(vec_bytes) } else { // TODO(16): return capacity allocation when we can safely do that. let mut result = Vec::with_capacity(hint::cautious::(len)); for _ in 0..len { - result.push(T::deserialize_reader(reader)?); + result.push(if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader_async(reader).await + }?); } Ok(result) } @@ -422,66 +616,124 @@ where } #[cfg(feature = "bytes")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for bytes::Bytes { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let vec = >::deserialize_reader(reader)?; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader_async(reader).await + }?; Ok(vec.into()) } } #[cfg(feature = "bytes")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for bytes::BytesMut { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let len = u32::deserialize_reader(reader)?; + let len = if _sync { + u32::deserialize_reader(reader) + } else { + u32::deserialize_reader_async(reader).await + }?; let mut out = BytesMut::with_capacity(hint::cautious::(len)); for _ in 0..len { - out.put_u8(u8::deserialize_reader(reader)?); + out.put_u8(if _sync { + u8::deserialize_reader(reader) + } else { + u8::deserialize_reader_async(reader).await + }?); } Ok(out) } } #[cfg(feature = "bson")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for bson::oid::ObjectId { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 12]; - reader.read_exact(&mut buf)?; + if _sync { + reader.read_exact(&mut buf) + } else { + reader.read_exact(&mut buf).await + }?; Ok(bson::oid::ObjectId::from_bytes(buf)) } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for Cow<'_, T> where T: ToOwned + ?Sized, T::Owned: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - Ok(Cow::Owned(BorshDeserialize::deserialize_reader(reader)?)) + Ok(Cow::Owned(if _sync { + BorshDeserialize::deserialize_reader(reader) + } else { + BorshDeserialize::deserialize_reader_async(reader).await + }?)) } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for VecDeque where T: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let vec = >::deserialize_reader(reader)?; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader_async(reader).await + }?; Ok(vec.into()) } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for LinkedList where T: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let vec = >::deserialize_reader(reader)?; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader_async(reader).await + }?; Ok(vec.into_iter().collect::>()) } } @@ -494,10 +746,20 @@ where pub mod hashes { use core::hash::{BuildHasher, Hash}; - use crate::BorshDeserialize; - use crate::__private::maybestd::collections::{HashMap, HashSet}; - use crate::__private::maybestd::vec::Vec; - use crate::io::{Read, Result}; + use async_generic::async_generic; + #[cfg(feature = "async")] + use async_trait::async_trait; + + #[cfg(feature = "async")] + use super::AsyncRead; + use crate::{ + BorshDeserialize, + __private::maybestd::{ + collections::{HashMap, HashSet}, + vec::Vec, + }, + io::{Read, Result}, + }; #[cfg(feature = "de_strict_order")] const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order"; @@ -505,18 +767,27 @@ pub mod hashes { #[cfg(feature = "de_strict_order")] use crate::io::{Error, ErrorKind}; + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for HashSet where T: BorshDeserialize + Eq + Hash + Ord, H: BuildHasher + Default, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the elements // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster - let vec = >::deserialize_reader(reader)?; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader_async(reader).await + }?; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -538,6 +809,7 @@ pub mod hashes { } } + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for HashMap where K: BorshDeserialize + Eq + Hash + Ord, @@ -545,13 +817,21 @@ pub mod hashes { H: BuildHasher + Default, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the entries // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster - let vec = >::deserialize_reader(reader)?; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader_async(reader).await + }?; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -574,17 +854,26 @@ pub mod hashes { } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for BTreeSet where T: BorshDeserialize + Ord, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the elements // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster - let vec = >::deserialize_reader(reader)?; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader_async(reader).await + }?; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -607,19 +896,28 @@ where } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for BTreeMap where K: BorshDeserialize + Ord, V: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the entries // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster - let vec = >::deserialize_reader(reader)?; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader_async(reader).await + }?; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -644,13 +942,32 @@ where } #[cfg(feature = "std")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for std::net::SocketAddr { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let kind = u8::deserialize_reader(reader)?; + let kind = if _sync { + u8::deserialize_reader(reader) + } else { + u8::deserialize_reader_async(reader).await + }?; match kind { - 0 => std::net::SocketAddrV4::deserialize_reader(reader).map(std::net::SocketAddr::V4), - 1 => std::net::SocketAddrV6::deserialize_reader(reader).map(std::net::SocketAddr::V6), + 0 => if _sync { + std::net::SocketAddrV4::deserialize_reader(reader) + } else { + std::net::SocketAddrV4::deserialize_reader_async(reader).await + } + .map(std::net::SocketAddr::V4), + 1 => if _sync { + std::net::SocketAddrV6::deserialize_reader(reader) + } else { + std::net::SocketAddrV6::deserialize_reader_async(reader).await + } + .map(std::net::SocketAddr::V6), value => Err(Error::new( ErrorKind::InvalidData, format!("Invalid SocketAddr variant: {}", value), @@ -660,19 +977,32 @@ impl BorshDeserialize for std::net::SocketAddr { } #[cfg(feature = "std")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for std::net::IpAddr { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let kind = u8::deserialize_reader(reader)?; match kind { - 0u8 => { + 0 => { // Deserialize an Ipv4Addr and convert it to IpAddr::V4 - let ipv4_addr = std::net::Ipv4Addr::deserialize_reader(reader)?; + let ipv4_addr = if _sync { + std::net::Ipv4Addr::deserialize_reader(reader) + } else { + std::net::Ipv4Addr::deserialize_reader_async(reader).await + }?; Ok(std::net::IpAddr::V4(ipv4_addr)) } - 1u8 => { + 1 => { // Deserialize an Ipv6Addr and convert it to IpAddr::V6 - let ipv6_addr = std::net::Ipv6Addr::deserialize_reader(reader)?; + let ipv6_addr = if _sync { + std::net::Ipv6Addr::deserialize_reader(reader) + } else { + std::net::Ipv6Addr::deserialize_reader_async(reader).await + }?; Ok(std::net::IpAddr::V6(ipv6_addr)) } value => Err(Error::new( @@ -684,65 +1014,117 @@ impl BorshDeserialize for std::net::IpAddr { } #[cfg(feature = "std")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for std::net::SocketAddrV4 { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let ip = std::net::Ipv4Addr::deserialize_reader(reader)?; - let port = u16::deserialize_reader(reader)?; + let ip = if _sync { + std::net::Ipv4Addr::deserialize_reader(reader) + } else { + std::net::Ipv4Addr::deserialize_reader_async(reader).await + }?; + let port = if _sync { + u16::deserialize_reader(reader) + } else { + u16::deserialize_reader_async(reader).await + }?; Ok(std::net::SocketAddrV4::new(ip, port)) } } #[cfg(feature = "std")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for std::net::SocketAddrV6 { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let ip = std::net::Ipv6Addr::deserialize_reader(reader)?; - let port = u16::deserialize_reader(reader)?; + let ip = if _sync { + std::net::Ipv6Addr::deserialize_reader(reader) + } else { + std::net::Ipv6Addr::deserialize_reader_async(reader).await + }?; + let port = if _sync { + u16::deserialize_reader(reader) + } else { + u16::deserialize_reader_async(reader).await + }?; Ok(std::net::SocketAddrV6::new(ip, port, 0, 0)) } } #[cfg(feature = "std")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for std::net::Ipv4Addr { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 4]; - reader - .read_exact(&mut buf) + let res = reader.read_exact(&mut buf); + if _sync { res } else { res.await } .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(std::net::Ipv4Addr::from(buf)) } } #[cfg(feature = "std")] +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for std::net::Ipv6Addr { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 16]; - reader - .read_exact(&mut buf) + let res = reader.read_exact(&mut buf); + if _sync { res } else { res.await } .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(std::net::Ipv6Addr::from(buf)) } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for Box where U: Into> + Borrow, T: ToOwned + ?Sized, T::Owned: BorshDeserialize, { + #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - Ok(T::Owned::deserialize_reader(reader)?.into()) + Ok(if _sync { + T::Owned::deserialize_reader(reader) + } else { + T::Owned::deserialize_reader_async(reader).await + }? + .into()) } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for [T; N] where T: BorshDeserialize, { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { struct ArrayDropGuard { buffer: [MaybeUninit; N], @@ -780,7 +1162,11 @@ where } } - if let Some(arr) = T::array_from_reader(reader)? { + if let Some(arr) = if _sync { + T::array_from_reader(reader) + } else { + T::array_from_reader_async(reader).await + }? { Ok(arr) } else { let mut result = ArrayDropGuard { @@ -788,7 +1174,13 @@ where init_count: 0, }; - result.fill_buffer(|| T::deserialize_reader(reader))?; + result.fill_buffer(|| { + if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader_async(reader).await + } + })?; // SAFETY: The elements up to `i` have been initialized in `fill_buffer`. Ok(unsafe { result.transmute_to_array() }) @@ -805,9 +1197,19 @@ fn array_deserialization_doesnt_leak() { #[allow(unused)] struct MyType(u8); + + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for MyType { + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let val = u8::deserialize_reader(reader)?; + let val = if _sync { + u8::deserialize_reader(reader) + } else { + u8::deserialize_reader_async(reader).await + }?; let v = DESERIALIZE_COUNT.fetch_add(1, Ordering::SeqCst); if v >= 7 { panic!("panic in deserialize"); @@ -843,8 +1245,13 @@ fn array_deserialization_doesnt_leak() { macro_rules! impl_tuple { (@unit $name:ty) => { + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for $name { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(_reader: &mut R) -> Result { Ok(<$name>::default()) } @@ -852,15 +1259,23 @@ macro_rules! impl_tuple { }; ($($name:ident)+) => { - impl<$($name),+> BorshDeserialize for ($($name,)+) - where $($name: BorshDeserialize,)+ - { - #[inline] - fn deserialize_reader(reader: &mut R) -> Result { - - Ok(($($name::deserialize_reader(reader)?,)+)) + #[async_generic(cfg_attr(feature = "async", async_trait))] + impl<$($name),+> BorshDeserialize for ($($name,)+) + where $($name: BorshDeserialize,)+ + { + #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] + fn deserialize_reader(reader: &mut R) -> Result { + Ok(if _sync { + ($($name::deserialize_reader(reader)?,)+) + } else { + ($($name::deserialize_reader_async(reader).await?,)+) + }) + } } - } }; } @@ -890,10 +1305,19 @@ impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T1 macro_rules! impl_range { ($type:ident, $make:expr, $($side:ident),*) => { + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for core::ops::$type { #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - let ($($side,)*) = <_>::deserialize_reader(reader)?; + let ($($side,)*) = if _sync { + <_>::deserialize_reader(reader) + } else { + <_>::deserialize_reader_async(reader).await + }?; Ok($make) } } @@ -912,21 +1336,41 @@ pub mod rc { //! //! Module defines [BorshDeserialize] implementation for //! [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). - use crate::__private::maybestd::{boxed::Box, rc::Rc, sync::Arc}; - use crate::io::{Read, Result}; - use crate::BorshDeserialize; + + use async_generic::async_generic; + #[cfg(feature = "async")] + use async_trait::async_trait; + + #[cfg(feature = "async")] + use super::AsyncRead; + use crate::{ + __private::maybestd::{boxed::Box, rc::Rc, sync::Arc}, + io::{Read, Result}, + BorshDeserialize, + }; /// This impl requires the [`"rc"`] Cargo feature of borsh. /// /// Deserializing a data structure containing `Rc` will not attempt to /// deduplicate `Rc` references to the same data. Every deserialized `Rc` /// will end up with a strong count of 1. + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for Rc where Box: BorshDeserialize, { + #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - Ok(Box::::deserialize_reader(reader)?.into()) + Ok(if _sync { + Box::::deserialize_reader(reader) + } else { + Box::::deserialize_reader_async(reader).await + }? + .into()) } } @@ -935,37 +1379,76 @@ pub mod rc { /// Deserializing a data structure containing `Arc` will not attempt to /// deduplicate `Arc` references to the same data. Every deserialized `Arc` /// will end up with a strong count of 1. + #[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for Arc where Box: BorshDeserialize, { + #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - Ok(Box::::deserialize_reader(reader)?.into()) + Ok(if _sync { + Box::::deserialize_reader(reader) + } else { + Box::::deserialize_reader_async(reader).await + }? + .into()) } } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for PhantomData { + #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(_: &mut R) -> Result + )] fn deserialize_reader(_: &mut R) -> Result { Ok(PhantomData) } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for core::cell::Cell where T: BorshDeserialize + Copy, { + #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - ::deserialize_reader(reader).map(core::cell::Cell::new) + if _sync { + ::deserialize_reader(reader) + } else { + ::deserialize_reader_async(reader).await + } + .map(core::cell::Cell::new) } } +#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for core::cell::RefCell where T: BorshDeserialize, { + #[inline] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { - ::deserialize_reader(reader).map(core::cell::RefCell::new) + if _sync { + ::deserialize_reader(reader) + } else { + ::deserialize_reader_async(reader).await + } + .map(core::cell::RefCell::new) } } @@ -1031,10 +1514,22 @@ pub fn from_slice(v: &[u8]) -> Result { /// # #[cfg(feature = "derive")] /// assert_eq!(original, decoded); /// ``` +#[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result +)] pub fn from_reader(reader: &mut R) -> Result { - let result = T::deserialize_reader(reader)?; + let result = if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader_async(reader).await + }?; let mut buf = [0u8; 1]; - match reader.read_exact(&mut buf) { + match if _sync { + reader.read_exact(&mut buf) + } else { + reader.read_exact(&mut buf).await + } { Err(f) if f.kind() == ErrorKind::UnexpectedEof => Ok(result), _ => Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)), } diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index ba4ce6501..002f65b87 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -41,6 +41,9 @@ pub mod error; #[cfg(all(feature = "std", feature = "hashbrown"))] compile_error!("feature \"std\" and feature \"hashbrown\" don't make sense at the same time"); +#[cfg(all(feature = "tokio", feature = "async-std"))] +compile_error!("Cannot enable both `async-tokio` and `async-std` features at the same time"); + #[cfg(feature = "std")] use std::io as io_impl; #[cfg(not(feature = "std"))] diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 000000000..030dbec30 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,4 @@ +edition = "2018" +unstable_features = true +group_imports = "StdExternalCrate" +imports_granularity = "Crate" \ No newline at end of file From 23a292f54a334400cd000ec587f2d8d611d993c3 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 21 Jan 2025 23:26:24 +0200 Subject: [PATCH 02/69] resolved issue with type parameters needing `Send` bound --- borsh/Cargo.toml | 4 +- borsh/src/de/mod.rs | 586 +++++++++++++++++++++++++++++++------------- 2 files changed, 422 insertions(+), 168 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index b13aa9ea2..fbccf4cc7 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -43,8 +43,8 @@ bson = { version = "2", optional = true } async-generic = { git = "https://github.com/DanikVitek/async-generic.git", version = "2.0" } async-trait = { version = "0.1", optional = true } -tokio = { version = "1", features = ["io-util"], optional = true } -async-std = { version = "1", features = ["async-io"], optional = true } +tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } +async-std = { version = "1", default-features = false, features = ["std"], optional = true } [dev-dependencies] insta = "1.29.0" diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 401f3b499..4a6dace2e 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -36,7 +36,11 @@ const ERROR_INVALID_ZERO_VALUE: &str = "Expected a non-zero value"; const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order"; /// A data-structure that can be de-serialized from binary format by NBOR. -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] pub trait BorshDeserialize: Sized { /// Deserializes this instance from a given slice of bytes. /// Updates the buffer to point at the remaining bytes. @@ -46,7 +50,7 @@ pub trait BorshDeserialize: Sized { #[async_generic( #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result where Self: Send + async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result; @@ -62,13 +66,13 @@ pub trait BorshDeserialize: Sized { #[async_generic( #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result where Result: Send + async_signature(reader: &mut R) -> Result )] fn try_from_reader(reader: &mut R) -> Result { let result = if _sync { Self::deserialize_reader(reader) } else { - Self::deserialize_reader_async(reader).await + Self::deserialize_reader(reader).await }?; let mut buf = [0u8; 1]; @@ -84,8 +88,6 @@ pub trait BorshDeserialize: Sized { #[async_generic( #[cfg(feature = "async")] async_signature(len: u32, reader: &mut R) -> Result>> - where - Self: Send )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let _ = len; @@ -98,8 +100,6 @@ pub trait BorshDeserialize: Sized { #[async_generic( #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result> - where - Self: Send )] fn array_from_reader(reader: &mut R) -> Result> { let _ = reader; @@ -118,10 +118,12 @@ pub trait AsyncRead: Unpin + Send { #[cfg(feature = "tokio")] #[async_trait] impl AsyncRead for R { + #[inline] async fn read(&mut self, buf: &mut [u8]) -> Result { tokio::io::AsyncReadExt::read(self, buf).await } + #[inline] async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { tokio::io::AsyncReadExt::read_exact(self, buf) .await @@ -132,16 +134,23 @@ impl AsyncRead for R { #[cfg(feature = "async-std")] #[async_trait] impl AsyncRead for R { + #[inline] async fn read(&mut self, buf: &mut [u8]) -> Result { async_std::io::ReadExt::read(self, buf).await } + #[inline] async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { async_std::io::ReadExt::read_exact(self, buf).await } } /// Additional methods offered on enums which is used by `[derive(BorshDeserialize)]`. +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] pub trait EnumExt: BorshDeserialize { /// Deserialises given variant of an enum from the reader. /// @@ -196,6 +205,10 @@ pub trait EnumExt: BorshDeserialize { /// # #[cfg(feature = "derive")] /// assert!(from_slice::(&data[..]).is_err()); /// ``` + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R, tag: u8) -> Result + )] fn deserialize_variant(reader: &mut R, tag: u8) -> Result; } @@ -207,7 +220,11 @@ fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for u8 { #[inline] #[async_generic( @@ -226,7 +243,7 @@ impl BorshDeserialize for u8 { #[doc(hidden)] #[async_generic( #[cfg(feature = "async")] - async_signature(len: u32, reader: &mut R) -> Result>> where Self: Send + async_signature(len: u32, reader: &mut R) -> Result>> )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let len: usize = len.try_into().map_err(|_| ErrorKind::InvalidData)?; @@ -276,13 +293,17 @@ impl BorshDeserialize for u8 { macro_rules! impl_for_integer { ($type: ident) => { - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for $type { #[inline] #[async_generic( - #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result - )] + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; size_of::<$type>()]; let res = reader.read_exact(&mut buf); @@ -307,7 +328,11 @@ impl_for_integer!(u128); macro_rules! impl_for_nonzero_integer { ($type: ty) => { - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for $type { #[inline] #[async_generic( @@ -315,13 +340,11 @@ macro_rules! impl_for_nonzero_integer { async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { - <$type>::new( - if _sync { - BorshDeserialize::deserialize_reader(reader) - } else { - BorshDeserialize::deserialize_reader_async(reader).await - }? - ) + <$type>::new(if _sync { + BorshDeserialize::deserialize_reader(reader) + } else { + BorshDeserializeAsync::deserialize_reader(reader).await + }?) .ok_or_else(|| Error::new(ErrorKind::InvalidData, ERROR_INVALID_ZERO_VALUE)) } } @@ -342,7 +365,11 @@ impl_for_nonzero_integer!(core::num::NonZeroUsize); macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for $type { #[async_generic( #[cfg(feature = "async")] @@ -352,11 +379,10 @@ macro_rules! impl_for_size_integer { let i: $temp_type = if _sync { BorshDeserialize::deserialize_reader(reader) } else { - BorshDeserialize::deserialize_reader_async(reader).await + BorshDeserializeAsync::deserialize_reader(reader).await }?; - let i = <$type>::try_from(i).map_err(|_| { - Error::new(ErrorKind::InvalidData, $msg) - })?; + let i = + <$type>::try_from(i).map_err(|_| Error::new(ErrorKind::InvalidData, $msg))?; Ok(i) } } @@ -370,7 +396,11 @@ impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); // and vice versa. We disallow NaNs to avoid this issue. macro_rules! impl_for_float { ($type: ident, $int_type: ident) => { - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for $type { #[inline] #[async_generic( @@ -398,7 +428,11 @@ macro_rules! impl_for_float { impl_for_float!(f32, u32); impl_for_float!(f64, u64); -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for bool { #[inline] #[async_generic( @@ -409,7 +443,7 @@ impl BorshDeserialize for bool { let b: u8 = if _sync { BorshDeserialize::deserialize_reader(reader) } else { - BorshDeserialize::deserialize_reader_async(reader).await + BorshDeserializeAsync::deserialize_reader(reader).await }?; if b == 0 { Ok(false) @@ -423,7 +457,13 @@ impl BorshDeserialize for bool { } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync, +)] impl BorshDeserialize for Option where T: BorshDeserialize, @@ -437,14 +477,14 @@ where let flag: u8 = if _sync { BorshDeserialize::deserialize_reader(reader) } else { - BorshDeserialize::deserialize_reader_async(reader).await + BorshDeserializeAsync::deserialize_reader(reader).await }?; match flag { 0 => Ok(None), 1 => Ok(Some(if _sync { T::deserialize_reader(reader) } else { - T::deserialize_reader_async(reader).await + T::deserialize_reader(reader).await }?)), _ => { let msg = format!( @@ -458,7 +498,14 @@ where } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync, + E: BorshDeserializeAsync, +)] impl BorshDeserialize for core::result::Result where T: BorshDeserialize, @@ -473,18 +520,18 @@ where let flag: u8 = if _sync { BorshDeserialize::deserialize_reader(reader) } else { - BorshDeserialize::deserialize_reader_async(reader).await + BorshDeserializeAsync::deserialize_reader(reader).await }?; match flag { 0 => Ok(Err(if _sync { E::deserialize_reader(reader) } else { - E::deserialize_reader_async(reader).await + E::deserialize_reader(reader).await }?)), 1 => Ok(Ok(if _sync { T::deserialize_reader(reader) } else { - T::deserialize_reader_async(reader).await + T::deserialize_reader(reader).await }?)), _ => { let msg = format!( @@ -498,7 +545,11 @@ where } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for String { #[inline] #[async_generic( @@ -507,9 +558,9 @@ impl BorshDeserialize for String { )] fn deserialize_reader(reader: &mut R) -> Result { String::from_utf8(if _sync { - Vec::::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - Vec::::deserialize_reader_async(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?) .map_err(|err| { let msg = err.to_string(); @@ -529,15 +580,19 @@ pub mod ascii { #[cfg(feature = "async")] use async_trait::async_trait; + use super::BorshDeserialize; #[cfg(feature = "async")] - use super::AsyncRead; + use super::{AsyncRead, BorshDeserializeAsync}; use crate::{ - BorshDeserialize, __private::maybestd::{string::ToString, vec::Vec}, io::{Error, ErrorKind, Read, Result}, }; - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for ascii::AsciiString { #[inline] #[async_generic( @@ -546,16 +601,20 @@ pub mod ascii { )] fn deserialize_reader(reader: &mut R) -> Result { let bytes = if _sync { - Vec::::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - Vec::::deserialize_reader_async(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; ascii::AsciiString::from_ascii(bytes) .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())) } } - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for ascii::AsciiChar { #[inline] #[async_generic( @@ -564,9 +623,9 @@ pub mod ascii { )] fn deserialize_reader(reader: &mut R) -> Result { let byte = if _sync { - u8::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u8::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; ascii::AsciiChar::from_ascii(byte) .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())) @@ -574,7 +633,13 @@ pub mod ascii { } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync + Send, +)] impl BorshDeserialize for Vec where T: BorshDeserialize, @@ -588,16 +653,16 @@ where check_zst::()?; let len = if _sync { - u32::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u32::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; if len == 0 { Ok(Vec::new()) } else if let Some(vec_bytes) = if _sync { T::vec_from_reader(len, reader) } else { - T::vec_from_reader_async(len, reader).await + T::vec_from_reader(len, reader).await }? { Ok(vec_bytes) } else { @@ -607,7 +672,7 @@ where result.push(if _sync { T::deserialize_reader(reader) } else { - T::deserialize_reader_async(reader).await + T::deserialize_reader(reader).await }?); } Ok(result) @@ -616,7 +681,11 @@ where } #[cfg(feature = "bytes")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for bytes::Bytes { #[inline] #[async_generic( @@ -625,17 +694,21 @@ impl BorshDeserialize for bytes::Bytes { )] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { - >::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - >::deserialize_reader_async(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; Ok(vec.into()) } } #[cfg(feature = "bytes")] -#[async_generic(cfg_attr(feature = "async", async_trait))] -impl BorshDeserialize for bytes::BytesMut { +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] +impl BorshDeserialize for BytesMut { #[inline] #[async_generic( #[cfg(feature = "async")] @@ -643,16 +716,16 @@ impl BorshDeserialize for bytes::BytesMut { )] fn deserialize_reader(reader: &mut R) -> Result { let len = if _sync { - u32::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u32::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; let mut out = BytesMut::with_capacity(hint::cautious::(len)); for _ in 0..len { out.put_u8(if _sync { - u8::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u8::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?); } Ok(out) @@ -660,7 +733,11 @@ impl BorshDeserialize for bytes::BytesMut { } #[cfg(feature = "bson")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for bson::oid::ObjectId { #[inline] #[async_generic( @@ -678,7 +755,14 @@ impl BorshDeserialize for bson::oid::ObjectId { } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: ToOwned + ?Sized, + T::Owned: BorshDeserializeAsync, +)] impl BorshDeserialize for Cow<'_, T> where T: ToOwned + ?Sized, @@ -693,12 +777,18 @@ where Ok(Cow::Owned(if _sync { BorshDeserialize::deserialize_reader(reader) } else { - BorshDeserialize::deserialize_reader_async(reader).await + BorshDeserializeAsync::deserialize_reader(reader).await }?)) } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync + Send, +)] impl BorshDeserialize for VecDeque where T: BorshDeserialize, @@ -710,15 +800,21 @@ where )] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { - >::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - >::deserialize_reader_async(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; Ok(vec.into()) } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync + Send, +)] impl BorshDeserialize for LinkedList where T: BorshDeserialize, @@ -730,9 +826,9 @@ where )] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { - >::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - >::deserialize_reader_async(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; Ok(vec.into_iter().collect::>()) } @@ -750,24 +846,31 @@ pub mod hashes { #[cfg(feature = "async")] use async_trait::async_trait; + use super::BorshDeserialize; #[cfg(feature = "async")] - use super::AsyncRead; + use super::{AsyncRead, BorshDeserializeAsync}; + #[cfg(feature = "de_strict_order")] + use crate::io::{Error, ErrorKind}; use crate::{ - BorshDeserialize, __private::maybestd::{ collections::{HashMap, HashSet}, vec::Vec, }, + error::check_zst, io::{Read, Result}, }; #[cfg(feature = "de_strict_order")] const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order"; - use crate::error::check_zst; - #[cfg(feature = "de_strict_order")] - use crate::io::{Error, ErrorKind}; - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync + Eq + Hash + Ord + Send, + H: BuildHasher + Default, + )] impl BorshDeserialize for HashSet where T: BorshDeserialize + Eq + Hash + Ord, @@ -784,9 +887,9 @@ pub mod hashes { // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster let vec = if _sync { - >::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - >::deserialize_reader_async(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -809,7 +912,15 @@ pub mod hashes { } } - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + K: BorshDeserializeAsync + Eq + Hash + Ord + Send, + V: BorshDeserializeAsync + Send, + H: BuildHasher + Default, + )] impl BorshDeserialize for HashMap where K: BorshDeserialize + Eq + Hash + Ord, @@ -830,7 +941,7 @@ pub mod hashes { let vec = if _sync { >::deserialize_reader(reader) } else { - >::deserialize_reader_async(reader).await + >::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -854,7 +965,13 @@ pub mod hashes { } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync + Ord + Send, +)] impl BorshDeserialize for BTreeSet where T: BorshDeserialize + Ord, @@ -870,9 +987,9 @@ where // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster let vec = if _sync { - >::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - >::deserialize_reader_async(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -896,7 +1013,14 @@ where } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + K: BorshDeserializeAsync + Ord + Send, + V: BorshDeserializeAsync + Send, +)] impl BorshDeserialize for BTreeMap where K: BorshDeserialize + Ord, @@ -916,7 +1040,7 @@ where let vec = if _sync { >::deserialize_reader(reader) } else { - >::deserialize_reader_async(reader).await + >::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -942,7 +1066,11 @@ where } #[cfg(feature = "std")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for std::net::SocketAddr { #[inline] #[async_generic( @@ -951,21 +1079,21 @@ impl BorshDeserialize for std::net::SocketAddr { )] fn deserialize_reader(reader: &mut R) -> Result { let kind = if _sync { - u8::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u8::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; match kind { 0 => if _sync { - std::net::SocketAddrV4::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - std::net::SocketAddrV4::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await } .map(std::net::SocketAddr::V4), 1 => if _sync { - std::net::SocketAddrV6::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - std::net::SocketAddrV6::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await } .map(std::net::SocketAddr::V6), value => Err(Error::new( @@ -977,7 +1105,11 @@ impl BorshDeserialize for std::net::SocketAddr { } #[cfg(feature = "std")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for std::net::IpAddr { #[inline] #[async_generic( @@ -985,23 +1117,27 @@ impl BorshDeserialize for std::net::IpAddr { async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { - let kind = u8::deserialize_reader(reader)?; + let kind = if _sync { + ::deserialize_reader(reader) + } else { + ::deserialize_reader(reader).await + }?; match kind { 0 => { // Deserialize an Ipv4Addr and convert it to IpAddr::V4 let ipv4_addr = if _sync { - std::net::Ipv4Addr::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - std::net::Ipv4Addr::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; Ok(std::net::IpAddr::V4(ipv4_addr)) } 1 => { // Deserialize an Ipv6Addr and convert it to IpAddr::V6 let ipv6_addr = if _sync { - std::net::Ipv6Addr::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - std::net::Ipv6Addr::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; Ok(std::net::IpAddr::V6(ipv6_addr)) } @@ -1014,7 +1150,11 @@ impl BorshDeserialize for std::net::IpAddr { } #[cfg(feature = "std")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for std::net::SocketAddrV4 { #[inline] #[async_generic( @@ -1023,21 +1163,25 @@ impl BorshDeserialize for std::net::SocketAddrV4 { )] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { - std::net::Ipv4Addr::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - std::net::Ipv4Addr::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; let port = if _sync { - u16::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u16::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; Ok(std::net::SocketAddrV4::new(ip, port)) } } #[cfg(feature = "std")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for std::net::SocketAddrV6 { #[inline] #[async_generic( @@ -1046,21 +1190,25 @@ impl BorshDeserialize for std::net::SocketAddrV6 { )] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { - std::net::Ipv6Addr::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - std::net::Ipv6Addr::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; let port = if _sync { - u16::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u16::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; Ok(std::net::SocketAddrV6::new(ip, port, 0, 0)) } } #[cfg(feature = "std")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for std::net::Ipv4Addr { #[inline] #[async_generic( @@ -1077,7 +1225,11 @@ impl BorshDeserialize for std::net::Ipv4Addr { } #[cfg(feature = "std")] -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for std::net::Ipv6Addr { #[inline] #[async_generic( @@ -1093,7 +1245,15 @@ impl BorshDeserialize for std::net::Ipv6Addr { } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + U: Into> + Borrow, + T: ToOwned + ?Sized, + T::Owned: BorshDeserializeAsync, +)] impl BorshDeserialize for Box where U: Into> + Borrow, @@ -1109,22 +1269,17 @@ where Ok(if _sync { T::Owned::deserialize_reader(reader) } else { - T::Owned::deserialize_reader_async(reader).await + T::Owned::deserialize_reader(reader).await }? .into()) } } -#[async_generic(cfg_attr(feature = "async", async_trait))] impl BorshDeserialize for [T; N] where T: BorshDeserialize, { #[inline] - #[async_generic( - #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result - )] fn deserialize_reader(reader: &mut R) -> Result { struct ArrayDropGuard { buffer: [MaybeUninit; N], @@ -1162,11 +1317,7 @@ where } } - if let Some(arr) = if _sync { - T::array_from_reader(reader) - } else { - T::array_from_reader_async(reader).await - }? { + if let Some(arr) = T::array_from_reader(reader)? { Ok(arr) } else { let mut result = ArrayDropGuard { @@ -1174,13 +1325,72 @@ where init_count: 0, }; - result.fill_buffer(|| { - if _sync { - T::deserialize_reader(reader) - } else { - T::deserialize_reader_async(reader).await + result.fill_buffer(|| T::deserialize_reader(reader))?; + + // SAFETY: The elements up to `i` have been initialized in `fill_buffer`. + Ok(unsafe { result.transmute_to_array() }) + } + } +} + +#[cfg(feature = "async")] +#[cfg_attr(feature = "async", async_trait)] +impl BorshDeserializeAsync for [T; N] +where + T: BorshDeserializeAsync + Send, +{ + #[inline] + async fn deserialize_reader(reader: &mut R) -> Result { + struct ArrayDropGuard<'r, T: BorshDeserializeAsync, const N: usize, R: AsyncRead> { + buffer: [MaybeUninit; N], + init_count: usize, + reader: &'r mut R, + } + impl<'r, T: BorshDeserializeAsync, const N: usize, R: AsyncRead> Drop + for ArrayDropGuard<'r, T, N, R> + { + fn drop(&mut self) { + let init_range = &mut self.buffer[..self.init_count]; + // SAFETY: Elements up to self.init_count have been initialized. Assumes this value + // is only incremented in `fill_buffer`, which writes the element before + // increasing the init_count. + unsafe { + core::ptr::drop_in_place(init_range as *mut _ as *mut [T]); + }; + } + } + + impl<'r, T: BorshDeserializeAsync, const N: usize, R: AsyncRead> ArrayDropGuard<'r, T, N, R> { + unsafe fn transmute_to_array(mut self) -> [T; N] { + debug_assert_eq!(self.init_count, N); + // Set init_count to 0 so that the values do not get dropped twice. + self.init_count = 0; + // SAFETY: This cast is required because `mem::transmute` does not work with + // const generics https://github.com/rust-lang/rust/issues/61956. This + // array is guaranteed to be initialized by this point. + core::ptr::read(&self.buffer as *const _ as *const [T; N]) + } + async fn fill_buffer(&mut self) -> Result<()> { + // TODO: replace with `core::array::try_from_fn` when stabilized to avoid manually + // dropping uninitialized values through the guard drop. + for elem in self.buffer.iter_mut() { + elem.write(T::deserialize_reader(self.reader).await?); + self.init_count += 1; } - })?; + Ok(()) + } + } + + if let Some(arr) = T::array_from_reader(reader).await? { + Ok(arr) + } else { + let mut result = ArrayDropGuard { + buffer: unsafe { MaybeUninit::uninit().assume_init() }, + init_count: 0, + reader, + }; + + result.fill_buffer().await?; // SAFETY: The elements up to `i` have been initialized in `fill_buffer`. Ok(unsafe { result.transmute_to_array() }) @@ -1198,7 +1408,11 @@ fn array_deserialization_doesnt_leak() { #[allow(unused)] struct MyType(u8); - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for MyType { #[async_generic( #[cfg(feature = "async")] @@ -1206,9 +1420,9 @@ fn array_deserialization_doesnt_leak() { )] fn deserialize_reader(reader: &mut R) -> Result { let val = if _sync { - u8::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - u8::deserialize_reader_async(reader).await + ::deserialize_reader(reader).await }?; let v = DESERIALIZE_COUNT.fetch_add(1, Ordering::SeqCst); if v >= 7 { @@ -1245,12 +1459,16 @@ fn array_deserialization_doesnt_leak() { macro_rules! impl_tuple { (@unit $name:ty) => { - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for $name { #[inline] #[async_generic( #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result + async_signature(_reader: &mut R) -> Result )] fn deserialize_reader(_reader: &mut R) -> Result { Ok(<$name>::default()) @@ -1259,9 +1477,16 @@ macro_rules! impl_tuple { }; ($($name:ident)+) => { - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait<$($name),+> + where + $($name: BorshDeserializeAsync + Send,)+ + )] impl<$($name),+> BorshDeserialize for ($($name,)+) - where $($name: BorshDeserialize,)+ + where + $($name: BorshDeserialize,)+ { #[inline] #[async_generic( @@ -1272,7 +1497,7 @@ macro_rules! impl_tuple { Ok(if _sync { ($($name::deserialize_reader(reader)?,)+) } else { - ($($name::deserialize_reader_async(reader).await?,)+) + ($($name::deserialize_reader(reader).await?,)+) }) } } @@ -1305,18 +1530,22 @@ impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T1 macro_rules! impl_range { ($type:ident, $make:expr, $($side:ident),*) => { - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for core::ops::$type { #[inline] - #[async_generic( - #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result - )] + #[async_generic( + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let ($($side,)*) = if _sync { - <_>::deserialize_reader(reader) + BorshDeserialize::deserialize_reader(reader) } else { - <_>::deserialize_reader_async(reader).await + BorshDeserializeAsync::deserialize_reader(reader).await }?; Ok($make) } @@ -1341,12 +1570,12 @@ pub mod rc { #[cfg(feature = "async")] use async_trait::async_trait; + use super::BorshDeserialize; #[cfg(feature = "async")] - use super::AsyncRead; + use super::{AsyncRead, BorshDeserializeAsync}; use crate::{ __private::maybestd::{boxed::Box, rc::Rc, sync::Arc}, io::{Read, Result}, - BorshDeserialize, }; /// This impl requires the [`"rc"`] Cargo feature of borsh. @@ -1354,21 +1583,27 @@ pub mod rc { /// Deserializing a data structure containing `Rc` will not attempt to /// deduplicate `Rc` references to the same data. Every deserialized `Rc` /// will end up with a strong count of 1. - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + Box: BorshDeserializeAsync, + )] impl BorshDeserialize for Rc where Box: BorshDeserialize, { #[inline] #[async_generic( - #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result - )] + #[cfg(feature = "async")] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { Box::::deserialize_reader(reader) } else { - Box::::deserialize_reader_async(reader).await + Box::::deserialize_reader(reader).await }? .into()) } @@ -1379,7 +1614,13 @@ pub mod rc { /// Deserializing a data structure containing `Arc` will not attempt to /// deduplicate `Arc` references to the same data. Every deserialized `Arc` /// will end up with a strong count of 1. - #[async_generic(cfg_attr(feature = "async", async_trait))] + #[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + Box: BorshDeserializeAsync, + )] impl BorshDeserialize for Arc where Box: BorshDeserialize, @@ -1393,14 +1634,18 @@ pub mod rc { Ok(if _sync { Box::::deserialize_reader(reader) } else { - Box::::deserialize_reader_async(reader).await + Box::::deserialize_reader(reader).await }? .into()) } } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait +)] impl BorshDeserialize for PhantomData { #[inline] #[async_generic( @@ -1412,7 +1657,13 @@ impl BorshDeserialize for PhantomData { } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync + Copy, +)] impl BorshDeserialize for core::cell::Cell where T: BorshDeserialize + Copy, @@ -1424,15 +1675,21 @@ where )] fn deserialize_reader(reader: &mut R) -> Result { if _sync { - ::deserialize_reader(reader) + T::deserialize_reader(reader) } else { - ::deserialize_reader_async(reader).await + T::deserialize_reader(reader).await } .map(core::cell::Cell::new) } } -#[async_generic(cfg_attr(feature = "async", async_trait))] +#[async_generic( + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + where + T: BorshDeserializeAsync, +)] impl BorshDeserialize for core::cell::RefCell where T: BorshDeserialize, @@ -1444,9 +1701,9 @@ where )] fn deserialize_reader(reader: &mut R) -> Result { if _sync { - ::deserialize_reader(reader) + T::deserialize_reader(reader) } else { - ::deserialize_reader_async(reader).await + T::deserialize_reader(reader).await } .map(core::cell::RefCell::new) } @@ -1484,10 +1741,7 @@ pub fn from_slice(v: &[u8]) -> Result { let mut v_mut = v; let object = T::deserialize(&mut v_mut)?; if !v_mut.is_empty() { - return Err(Error::new( - ErrorKind::InvalidData, - crate::de::ERROR_NOT_ALL_BYTES_READ, - )); + return Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)); } Ok(object) } @@ -1516,13 +1770,13 @@ pub fn from_slice(v: &[u8]) -> Result { /// ``` #[async_generic( #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result + async_signature(reader: &mut R) -> Result )] pub fn from_reader(reader: &mut R) -> Result { let result = if _sync { T::deserialize_reader(reader) } else { - T::deserialize_reader_async(reader).await + T::deserialize_reader(reader).await }?; let mut buf = [0u8; 1]; match if _sync { From 5b7f19d81509b050ee9dd4818f7fac9ee5491028 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 21 Jan 2025 23:37:46 +0200 Subject: [PATCH 03/69] remove redundant `cfg_attr`s --- borsh/src/de/mod.rs | 59 ++++++--------------------------------------- 1 file changed, 7 insertions(+), 52 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 4a6dace2e..dd6fde966 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -49,7 +49,6 @@ pub trait BorshDeserialize: Sized { } #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result; @@ -65,7 +64,6 @@ pub trait BorshDeserialize: Sized { } #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn try_from_reader(reader: &mut R) -> Result { @@ -86,7 +84,6 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] #[async_generic( - #[cfg(feature = "async")] async_signature(len: u32, reader: &mut R) -> Result>> )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { @@ -98,7 +95,6 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result> )] fn array_from_reader(reader: &mut R) -> Result> { @@ -206,7 +202,6 @@ pub trait EnumExt: BorshDeserialize { /// assert!(from_slice::(&data[..]).is_err()); /// ``` #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R, tag: u8) -> Result )] fn deserialize_variant(reader: &mut R, tag: u8) -> Result; @@ -228,7 +223,6 @@ fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { impl BorshDeserialize for u8 { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -242,7 +236,6 @@ impl BorshDeserialize for u8 { #[inline] #[doc(hidden)] #[async_generic( - #[cfg(feature = "async")] async_signature(len: u32, reader: &mut R) -> Result>> )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { @@ -279,7 +272,6 @@ impl BorshDeserialize for u8 { #[inline] #[doc(hidden)] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result> )] fn array_from_reader(reader: &mut R) -> Result> { @@ -294,16 +286,15 @@ impl BorshDeserialize for u8 { macro_rules! impl_for_integer { ($type: ident) => { #[async_generic( - #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] - async_trait - )] + #[cfg(feature = "async")] + #[cfg_attr(feature = "async", async_trait)] + async_trait + )] impl BorshDeserialize for $type { #[inline] #[async_generic( - #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result - )] + async_signature(reader: &mut R) -> Result + )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; size_of::<$type>()]; let res = reader.read_exact(&mut buf); @@ -336,7 +327,6 @@ macro_rules! impl_for_nonzero_integer { impl BorshDeserialize for $type { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -372,7 +362,6 @@ macro_rules! impl_for_size_integer { )] impl BorshDeserialize for $type { #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -404,7 +393,6 @@ macro_rules! impl_for_float { impl BorshDeserialize for $type { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -436,7 +424,6 @@ impl_for_float!(f64, u64); impl BorshDeserialize for bool { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -470,7 +457,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -513,7 +499,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -553,7 +538,6 @@ where impl BorshDeserialize for String { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -596,7 +580,6 @@ pub mod ascii { impl BorshDeserialize for ascii::AsciiString { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -618,7 +601,6 @@ pub mod ascii { impl BorshDeserialize for ascii::AsciiChar { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -646,7 +628,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -689,7 +670,6 @@ where impl BorshDeserialize for bytes::Bytes { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -711,7 +691,6 @@ impl BorshDeserialize for bytes::Bytes { impl BorshDeserialize for BytesMut { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -741,7 +720,6 @@ impl BorshDeserialize for BytesMut { impl BorshDeserialize for bson::oid::ObjectId { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -770,7 +748,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -795,7 +772,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -821,7 +797,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -878,7 +853,6 @@ pub mod hashes { { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -929,7 +903,6 @@ pub mod hashes { { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -978,7 +951,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1028,7 +1000,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1074,7 +1045,6 @@ where impl BorshDeserialize for std::net::SocketAddr { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1113,7 +1083,6 @@ impl BorshDeserialize for std::net::SocketAddr { impl BorshDeserialize for std::net::IpAddr { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1158,7 +1127,6 @@ impl BorshDeserialize for std::net::IpAddr { impl BorshDeserialize for std::net::SocketAddrV4 { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1185,7 +1153,6 @@ impl BorshDeserialize for std::net::SocketAddrV4 { impl BorshDeserialize for std::net::SocketAddrV6 { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1212,7 +1179,6 @@ impl BorshDeserialize for std::net::SocketAddrV6 { impl BorshDeserialize for std::net::Ipv4Addr { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1233,7 +1199,6 @@ impl BorshDeserialize for std::net::Ipv4Addr { impl BorshDeserialize for std::net::Ipv6Addr { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1262,7 +1227,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1415,7 +1379,6 @@ fn array_deserialization_doesnt_leak() { )] impl BorshDeserialize for MyType { #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1467,7 +1430,6 @@ macro_rules! impl_tuple { impl BorshDeserialize for $name { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(_reader: &mut R) -> Result )] fn deserialize_reader(_reader: &mut R) -> Result { @@ -1490,7 +1452,6 @@ macro_rules! impl_tuple { { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1537,8 +1498,7 @@ macro_rules! impl_range { )] impl BorshDeserialize for core::ops::$type { #[inline] - #[async_generic( - #[cfg(feature = "async")] + #[async_generic( async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1596,7 +1556,6 @@ pub mod rc { { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1627,7 +1586,6 @@ pub mod rc { { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1649,7 +1607,6 @@ pub mod rc { impl BorshDeserialize for PhantomData { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(_: &mut R) -> Result )] fn deserialize_reader(_: &mut R) -> Result { @@ -1670,7 +1627,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { @@ -1696,7 +1652,6 @@ where { #[inline] #[async_generic( - #[cfg(feature = "async")] async_signature(reader: &mut R) -> Result )] fn deserialize_reader(reader: &mut R) -> Result { From cf2807c0463f631c845a34e96236c71e6c1edafd Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 22 Jan 2025 01:10:50 +0200 Subject: [PATCH 04/69] Implement async I/O for all standard types. TODO: derive, etc. --- borsh/src/async_io.rs | 61 ++++ borsh/src/de/mod.rs | 188 +++++------ borsh/src/lib.rs | 3 + borsh/src/ser/mod.rs | 727 +++++++++++++++++++++++++++++++++++------- 4 files changed, 746 insertions(+), 233 deletions(-) create mode 100644 borsh/src/async_io.rs diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs new file mode 100644 index 000000000..5d6f4638f --- /dev/null +++ b/borsh/src/async_io.rs @@ -0,0 +1,61 @@ +use async_trait::async_trait; + +#[async_trait] +pub trait AsyncRead: Unpin + Send { + async fn read(&mut self, buf: &mut [u8]) -> std::io::Result; + + async fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()>; +} + +#[cfg(feature = "tokio")] +#[async_trait] +impl AsyncRead for R { + #[inline] + async fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + tokio::io::AsyncReadExt::read(self, buf).await + } + + #[inline] + async fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { + tokio::io::AsyncReadExt::read_exact(self, buf) + .await + .map(|_| ()) + } +} + +#[cfg(feature = "async-std")] +#[async_trait] +impl AsyncRead for R { + #[inline] + async fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + async_std::io::ReadExt::read(self, buf).await + } + + #[inline] + async fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { + async_std::io::ReadExt::read_exact(self, buf).await + } +} + +#[async_trait] +pub trait AsyncWrite: Unpin + Send { + async fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()>; +} + +#[cfg(feature = "tokio")] +#[async_trait] +impl AsyncWrite for R { + #[inline] + async fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { + tokio::io::AsyncWriteExt::write_all(self, buf).await + } +} + +#[cfg(feature = "async-std")] +#[async_trait] +impl AsyncWrite for R { + #[inline] + async fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { + async_std::io::WriteExt::write_all(self, buf).await + } +} \ No newline at end of file diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index dd6fde966..a2ecd8d6a 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -23,6 +23,8 @@ use crate::{ error::check_zst, io::{Error, ErrorKind, Read, Result}, }; +#[cfg(feature = "async")] +use crate::async_io::AsyncRead; mod hint; @@ -38,8 +40,8 @@ const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending o /// A data-structure that can be de-serialized from binary format by NBOR. #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] - async_trait + #[async_trait] + async_trait: BorshDeserialize )] pub trait BorshDeserialize: Sized { /// Deserializes this instance from a given slice of bytes. @@ -68,9 +70,9 @@ pub trait BorshDeserialize: Sized { )] fn try_from_reader(reader: &mut R) -> Result { let result = if _sync { - Self::deserialize_reader(reader) + BorshDeserialize::deserialize_reader(reader) } else { - Self::deserialize_reader(reader).await + BorshDeserializeAsync::deserialize_reader(reader).await }?; let mut buf = [0u8; 1]; @@ -103,48 +105,10 @@ pub trait BorshDeserialize: Sized { } } -#[cfg(feature = "async")] -#[async_trait] -pub trait AsyncRead: Unpin + Send { - async fn read(&mut self, buf: &mut [u8]) -> Result; - - async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>; -} - -#[cfg(feature = "tokio")] -#[async_trait] -impl AsyncRead for R { - #[inline] - async fn read(&mut self, buf: &mut [u8]) -> Result { - tokio::io::AsyncReadExt::read(self, buf).await - } - - #[inline] - async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { - tokio::io::AsyncReadExt::read_exact(self, buf) - .await - .map(|_| ()) - } -} - -#[cfg(feature = "async-std")] -#[async_trait] -impl AsyncRead for R { - #[inline] - async fn read(&mut self, buf: &mut [u8]) -> Result { - async_std::io::ReadExt::read(self, buf).await - } - - #[inline] - async fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { - async_std::io::ReadExt::read_exact(self, buf).await - } -} - /// Additional methods offered on enums which is used by `[derive(BorshDeserialize)]`. #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] pub trait EnumExt: BorshDeserialize { @@ -217,7 +181,7 @@ fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for u8 { @@ -287,7 +251,7 @@ macro_rules! impl_for_integer { ($type: ident) => { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for $type { @@ -321,7 +285,7 @@ macro_rules! impl_for_nonzero_integer { ($type: ty) => { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for $type { @@ -357,7 +321,7 @@ macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for $type { @@ -387,7 +351,7 @@ macro_rules! impl_for_float { ($type: ident, $int_type: ident) => { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for $type { @@ -418,7 +382,7 @@ impl_for_float!(f64, u64); #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for bool { @@ -446,7 +410,7 @@ impl BorshDeserialize for bool { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync, @@ -468,9 +432,9 @@ where match flag { 0 => Ok(None), 1 => Ok(Some(if _sync { - T::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - T::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?)), _ => { let msg = format!( @@ -486,7 +450,7 @@ where #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync, @@ -509,14 +473,14 @@ where }?; match flag { 0 => Ok(Err(if _sync { - E::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - E::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?)), 1 => Ok(Ok(if _sync { - T::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - T::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?)), _ => { let msg = format!( @@ -532,7 +496,7 @@ where #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for String { @@ -574,7 +538,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for ascii::AsciiString { @@ -595,7 +559,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for ascii::AsciiChar { @@ -617,7 +581,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync + Send, @@ -641,9 +605,9 @@ where if len == 0 { Ok(Vec::new()) } else if let Some(vec_bytes) = if _sync { - T::vec_from_reader(len, reader) + ::vec_from_reader(len, reader) } else { - T::vec_from_reader(len, reader).await + ::vec_from_reader(len, reader).await }? { Ok(vec_bytes) } else { @@ -651,9 +615,9 @@ where let mut result = Vec::with_capacity(hint::cautious::(len)); for _ in 0..len { result.push(if _sync { - T::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - T::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?); } Ok(result) @@ -664,7 +628,7 @@ where #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for bytes::Bytes { @@ -685,7 +649,7 @@ impl BorshDeserialize for bytes::Bytes { #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for BytesMut { @@ -714,7 +678,7 @@ impl BorshDeserialize for BytesMut { #[cfg(feature = "bson")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for bson::oid::ObjectId { @@ -735,7 +699,7 @@ impl BorshDeserialize for bson::oid::ObjectId { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: ToOwned + ?Sized, @@ -761,7 +725,7 @@ where #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync + Send, @@ -786,7 +750,7 @@ where #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync + Send, @@ -840,7 +804,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync + Eq + Hash + Ord + Send, @@ -888,7 +852,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where K: BorshDeserializeAsync + Eq + Hash + Ord + Send, @@ -912,9 +876,9 @@ pub mod hashes { // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster let vec = if _sync { - >::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - >::deserialize_reader(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -940,7 +904,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync + Ord + Send, @@ -987,7 +951,7 @@ where #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where K: BorshDeserializeAsync + Ord + Send, @@ -1009,9 +973,9 @@ where // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster let vec = if _sync { - >::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - >::deserialize_reader(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -1039,7 +1003,7 @@ where #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for std::net::SocketAddr { @@ -1077,7 +1041,7 @@ impl BorshDeserialize for std::net::SocketAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for std::net::IpAddr { @@ -1121,7 +1085,7 @@ impl BorshDeserialize for std::net::IpAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for std::net::SocketAddrV4 { @@ -1147,7 +1111,7 @@ impl BorshDeserialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for std::net::SocketAddrV6 { @@ -1173,7 +1137,7 @@ impl BorshDeserialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for std::net::Ipv4Addr { @@ -1193,7 +1157,7 @@ impl BorshDeserialize for std::net::Ipv4Addr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for std::net::Ipv6Addr { @@ -1212,7 +1176,7 @@ impl BorshDeserialize for std::net::Ipv6Addr { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where U: Into> + Borrow, @@ -1231,9 +1195,9 @@ where )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { - T::Owned::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - T::Owned::deserialize_reader(reader).await + ::deserialize_reader(reader).await }? .into()) } @@ -1298,7 +1262,7 @@ where } #[cfg(feature = "async")] -#[cfg_attr(feature = "async", async_trait)] +#[async_trait] impl BorshDeserializeAsync for [T; N] where T: BorshDeserializeAsync + Send, @@ -1338,14 +1302,14 @@ where // TODO: replace with `core::array::try_from_fn` when stabilized to avoid manually // dropping uninitialized values through the guard drop. for elem in self.buffer.iter_mut() { - elem.write(T::deserialize_reader(self.reader).await?); + elem.write(::deserialize_reader(self.reader).await?); self.init_count += 1; } Ok(()) } } - if let Some(arr) = T::array_from_reader(reader).await? { + if let Some(arr) = ::array_from_reader(reader).await? { Ok(arr) } else { let mut result = ArrayDropGuard { @@ -1374,7 +1338,7 @@ fn array_deserialization_doesnt_leak() { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for MyType { @@ -1424,7 +1388,7 @@ macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for $name { @@ -1441,7 +1405,7 @@ macro_rules! impl_tuple { ($($name:ident)+) => { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait<$($name),+> where $($name: BorshDeserializeAsync + Send,)+ @@ -1456,9 +1420,9 @@ macro_rules! impl_tuple { )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { - ($($name::deserialize_reader(reader)?,)+) + ($(<$name as BorshDeserialize>::deserialize_reader(reader)?,)+) } else { - ($($name::deserialize_reader(reader).await?,)+) + ($(<$name as BorshDeserializeAsync>::deserialize_reader(reader).await?,)+) }) } } @@ -1493,7 +1457,7 @@ macro_rules! impl_range { ($type:ident, $make:expr, $($side:ident),*) => { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for core::ops::$type { @@ -1545,7 +1509,7 @@ pub mod rc { /// will end up with a strong count of 1. #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where Box: BorshDeserializeAsync, @@ -1560,9 +1524,9 @@ pub mod rc { )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { - Box::::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - Box::::deserialize_reader(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }? .into()) } @@ -1575,7 +1539,7 @@ pub mod rc { /// will end up with a strong count of 1. #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where Box: BorshDeserializeAsync, @@ -1590,9 +1554,9 @@ pub mod rc { )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { - Box::::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader) } else { - Box::::deserialize_reader(reader).await + as BorshDeserializeAsync>::deserialize_reader(reader).await }? .into()) } @@ -1601,7 +1565,7 @@ pub mod rc { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait )] impl BorshDeserialize for PhantomData { @@ -1616,7 +1580,7 @@ impl BorshDeserialize for PhantomData { #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync + Copy, @@ -1631,9 +1595,9 @@ where )] fn deserialize_reader(reader: &mut R) -> Result { if _sync { - T::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - T::deserialize_reader(reader).await + ::deserialize_reader(reader).await } .map(core::cell::Cell::new) } @@ -1641,7 +1605,7 @@ where #[async_generic( #[cfg(feature = "async")] - #[cfg_attr(feature = "async", async_trait)] + #[async_trait] async_trait where T: BorshDeserializeAsync, @@ -1656,9 +1620,9 @@ where )] fn deserialize_reader(reader: &mut R) -> Result { if _sync { - T::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - T::deserialize_reader(reader).await + ::deserialize_reader(reader).await } .map(core::cell::RefCell::new) } @@ -1729,9 +1693,9 @@ pub fn from_slice(v: &[u8]) -> Result { )] pub fn from_reader(reader: &mut R) -> Result { let result = if _sync { - T::deserialize_reader(reader) + ::deserialize_reader(reader) } else { - T::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?; let mut buf = [0u8; 1]; match if _sync { diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index 002f65b87..cf69044ed 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -48,6 +48,9 @@ compile_error!("Cannot enable both `async-tokio` and `async-std` features at the use std::io as io_impl; #[cfg(not(feature = "std"))] mod nostd_io; +#[cfg(feature = "async")] +pub mod async_io; + #[cfg(not(feature = "std"))] use nostd_io as io_impl; diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index b7da5ebd7..05e8913d4 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -1,15 +1,22 @@ -use core::convert::TryFrom; -use core::marker::PhantomData; - -use crate::__private::maybestd::{ - borrow::{Cow, ToOwned}, - boxed::Box, - collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, - string::String, - vec::Vec, +use core::{convert::TryFrom, marker::PhantomData}; + +use async_generic::async_generic; +#[cfg(feature = "async")] +use async_trait::async_trait; + +#[cfg(feature = "async")] +use crate::async_io::AsyncWrite; +use crate::{ + __private::maybestd::{ + borrow::{Cow, ToOwned}, + boxed::Box, + collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, + string::String, + vec::Vec, + }, + error::check_zst, + io::{Error, ErrorKind, Result, Write}, }; -use crate::error::check_zst; -use crate::io::{Error, ErrorKind, Result, Write}; pub(crate) mod helpers; @@ -48,7 +55,13 @@ const FLOAT_NAN_ERR: &str = "For portability reasons we do not allow to serializ /// # #[cfg(feature = "derive")] /// x.serialize(&mut buffer_slice_enough_for_the_data).unwrap(); /// ``` +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait: BorshSerialize +)] pub trait BorshSerialize { + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()>; #[inline] @@ -62,10 +75,21 @@ pub trait BorshSerialize { } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for u8 { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - writer.write_all(core::slice::from_ref(self)) + let res = writer.write_all(core::slice::from_ref(self)); + if _sync { + res + } else { + res.await + } } #[inline] @@ -76,11 +100,21 @@ impl BorshSerialize for u8 { macro_rules! impl_for_integer { ($type: ident) => { + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] impl BorshSerialize for $type { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.to_le_bytes(); - writer.write_all(&bytes) + if _sync { + writer.write_all(&bytes) + } else { + writer.write_all(&bytes).await + } } } }; @@ -98,10 +132,20 @@ impl_for_integer!(u128); macro_rules! impl_for_nonzero_integer { ($type: ty) => { + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] impl BorshSerialize for $type { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - BorshSerialize::serialize(&self.get(), writer) + if _sync { + BorshSerialize::serialize(&self.get(), writer) + } else { + BorshSerializeAsync::serialize(&self.get(), writer).await + } } } }; @@ -119,29 +163,52 @@ impl_for_nonzero_integer!(core::num::NonZeroU64); impl_for_nonzero_integer!(core::num::NonZeroU128); impl_for_nonzero_integer!(core::num::NonZeroUsize); -impl BorshSerialize for isize { - fn serialize(&self, writer: &mut W) -> Result<()> { - BorshSerialize::serialize(&(*self as i64), writer) - } +macro_rules! impl_for_size_integer { + ($type:ty: $repr:ty) => { + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] + impl BorshSerialize for $type { + #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + fn serialize(&self, writer: &mut W) -> Result<()> { + if _sync { + BorshSerialize::serialize(&(*self as $repr), writer) + } else { + BorshSerializeAsync::serialize(&(*self as $repr), writer).await + } + } + } + }; } -impl BorshSerialize for usize { - fn serialize(&self, writer: &mut W) -> Result<()> { - BorshSerialize::serialize(&(*self as u64), writer) - } -} +impl_for_size_integer!(usize: u64); +impl_for_size_integer!(isize: i64); // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, // and vice-versa. We disallow NaNs to avoid this issue. macro_rules! impl_for_float { ($type: ident) => { + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] impl BorshSerialize for $type { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { if self.is_nan() { return Err(Error::new(ErrorKind::InvalidData, FLOAT_NAN_ERR)); } - writer.write_all(&self.to_bits().to_le_bytes()) + let bytes = self.to_bits().to_le_bytes(); + if _sync { + writer.write_all(&bytes) + } else { + writer.write_all(&bytes).await + } } } }; @@ -150,60 +217,123 @@ macro_rules! impl_for_float { impl_for_float!(f32); impl_for_float!(f64); +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for bool { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - (u8::from(*self)).serialize(writer) + let byte = u8::from(*self); + if _sync { + BorshSerialize::serialize(&byte, writer) + } else { + BorshSerializeAsync::serialize(&byte, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, +)] impl BorshSerialize for Option where T: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { match self { - None => 0u8.serialize(writer), - Some(value) => { - 1u8.serialize(writer)?; - value.serialize(writer) - } + None => if _sync { + BorshSerialize::serialize(&0u8, writer) + } else { + BorshSerializeAsync::serialize(&0u8, writer).await + }, + Some(value) => if _sync { + BorshSerialize::serialize(&1u8, writer)?; + BorshSerialize::serialize(value, writer) + } else { + BorshSerializeAsync::serialize(&1u8, writer).await?; + BorshSerializeAsync::serialize(value, writer).await + }, } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, + E: BorshSerializeAsync + Sync, +)] impl BorshSerialize for core::result::Result where T: BorshSerialize, E: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { match self { - Err(e) => { - 0u8.serialize(writer)?; - e.serialize(writer) + Err(e) => if _sync { + BorshSerialize::serialize(&0u8, writer)?; + BorshSerialize::serialize(e, writer) + } else { + BorshSerializeAsync::serialize(&0u8, writer).await?; + BorshSerializeAsync::serialize(e, writer).await } - Ok(v) => { - 1u8.serialize(writer)?; - v.serialize(writer) + Ok(v) => if _sync { + BorshSerialize::serialize(&1u8, writer)?; + BorshSerialize::serialize(v, writer) + } else { + BorshSerializeAsync::serialize(&1u8, writer).await?; + BorshSerializeAsync::serialize(v, writer).await } } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for str { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_bytes().serialize(writer) + let bytes = self.as_bytes(); + if _sync { + BorshSerialize::serialize(bytes, writer) + } else { + BorshSerializeAsync::serialize(bytes, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for String { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_bytes().serialize(writer) + let bytes = self.as_bytes(); + if _sync { + BorshSerialize::serialize(bytes, writer) + } else { + BorshSerializeAsync::serialize(bytes, writer).await + } } } @@ -213,140 +343,305 @@ pub mod ascii { //! //! Module defines [BorshSerialize] implementation for //! some types from [ascii](::ascii) crate. + + use async_generic::async_generic; + #[cfg(feature = "async")] + use async_trait::async_trait; + use super::BorshSerialize; + #[cfg(feature = "async")] + use super::{AsyncWrite, BorshSerializeAsync}; use crate::io::{Result, Write}; + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] impl BorshSerialize for ascii::AsciiChar { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_byte().serialize(writer) + let byte = self.as_byte(); + if _sync { + BorshSerialize::serialize(&byte, writer) + } else { + BorshSerializeAsync::serialize(&byte, writer).await + } } } + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] impl BorshSerialize for ascii::AsciiStr { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_bytes().serialize(writer) + let bytes = self.as_bytes(); + if _sync { + BorshSerialize::serialize(bytes, writer) + } else { + BorshSerializeAsync::serialize(bytes, writer).await + } } } + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] impl BorshSerialize for ascii::AsciiString { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_bytes().serialize(writer) + let bytes = self.as_bytes(); + if _sync { + BorshSerialize::serialize(bytes, writer) + } else { + BorshSerializeAsync::serialize(bytes, writer).await + } } } } /// Helper method that is used to serialize a slice of data (without the length marker). #[inline] +#[async_generic( + #[cfg(feature = "async")] + async_signature( + data: &[T], + writer: &mut W + ) -> Result<()> +)] fn serialize_slice(data: &[T], writer: &mut W) -> Result<()> { if let Some(u8_slice) = T::u8_slice(data) { - writer.write_all(u8_slice)?; + if _sync { + writer.write_all(u8_slice) + } else { + writer.write_all(u8_slice).await + }?; } else { for item in data { - item.serialize(writer)?; + if _sync { + BorshSerialize::serialize(item, writer) + } else { + BorshSerializeAsync::serialize(item, writer).await + }?; } } Ok(()) } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, +)] impl BorshSerialize for [T] where T: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - writer.write_all( - &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(), - )?; - serialize_slice(self, writer) + let bytes = (u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(); + if _sync { + writer.write_all(&bytes)?; + serialize_slice(self, writer) + } else { + writer.write_all(&bytes).await?; + serialize_slice_async(self, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for &T { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - (*self).serialize(writer) + if _sync { + BorshSerialize::serialize(*self, writer) + } else { + BorshSerializeAsync::serialize(*self, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + ToOwned + ?Sized + Sync, + ::Owned: Sync, +)] impl BorshSerialize for Cow<'_, T> where T: BorshSerialize + ToOwned + ?Sized, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_ref().serialize(writer) + let r#ref = self.as_ref(); + if _sync { + BorshSerialize::serialize(r#ref, writer) + } else { + BorshSerializeAsync::serialize(r#ref, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, +)] impl BorshSerialize for Vec where T: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; - self.as_slice().serialize(writer) + let slice = self.as_slice(); + if _sync { + BorshSerialize::serialize(slice, writer) + } else { + BorshSerializeAsync::serialize(slice, writer).await + } } } #[cfg(feature = "bytes")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for bytes::Bytes { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_ref().serialize(writer) + let bytes = self.as_ref(); + if _sync { + BorshSerialize::serialize(bytes, writer) + } else { + BorshSerializeAsync::serialize(bytes, writer).await + } } } #[cfg(feature = "bytes")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for bytes::BytesMut { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_ref().serialize(writer) + let bytes = self.as_ref(); + if _sync { + BorshSerialize::serialize(bytes, writer) + } else { + BorshSerializeAsync::serialize(bytes, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] #[cfg(feature = "bson")] impl BorshSerialize for bson::oid::ObjectId { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.bytes().serialize(writer) + let bytes = self.bytes(); + if _sync { + BorshSerialize::serialize(&bytes, writer) + } else { + BorshSerializeAsync::serialize(&bytes, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, +)] impl BorshSerialize for VecDeque where T: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; - writer.write_all( - &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(), - )?; + let bytes = (u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(); let slices = self.as_slices(); - serialize_slice(slices.0, writer)?; - serialize_slice(slices.1, writer) + if _sync { + writer.write_all(&bytes)?; + serialize_slice(slices.0, writer)?; + serialize_slice(slices.1, writer) + } else { + writer.write_all(&bytes).await?; + serialize_slice_async(slices.0, writer).await?; + serialize_slice_async(slices.1, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, +)] impl BorshSerialize for LinkedList where T: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; - writer.write_all( - &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(), - )?; + let bytes =(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(); + if _sync { + writer.write_all(&bytes) + } else { + writer.write_all(&bytes).await + }?; for item in self { - item.serialize(writer)?; + if _sync { + BorshSerialize::serialize(item, writer) + } else { + BorshSerializeAsync::serialize(item, writer).await + }?; } Ok(()) } @@ -358,17 +653,33 @@ where /// [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { - use crate::__private::maybestd::vec::Vec; - use crate::error::check_zst; - use crate::{ - BorshSerialize, - __private::maybestd::collections::{HashMap, HashSet}, - }; - use core::convert::TryFrom; - use core::hash::BuildHasher; + use core::{convert::TryFrom, hash::BuildHasher}; - use crate::io::{ErrorKind, Result, Write}; + use async_generic::async_generic; + #[cfg(feature = "async")] + use async_trait::async_trait; + use crate::{ + __private::maybestd::{ + collections::{HashMap, HashSet}, + vec::Vec, + }, + error::check_zst, + io::{ErrorKind, Result, Write}, + }; + use super::BorshSerialize; + #[cfg(feature = "async")] + use super::{AsyncWrite, BorshSerializeAsync}; + + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + K: BorshSerializeAsync + Ord + Sync, + V: BorshSerializeAsync + Sync, + H: BuildHasher + Sync, + )] impl BorshSerialize for HashMap where K: BorshSerialize + Ord, @@ -376,180 +687,339 @@ pub mod hashes { H: BuildHasher, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; let mut vec = self.iter().collect::>(); vec.sort_by(|(a, _), (b, _)| a.cmp(b)); - u32::try_from(vec.len()) - .map_err(|_| ErrorKind::InvalidData)? - .serialize(writer)?; + let len = u32::try_from(vec.len()).map_err(|_| ErrorKind::InvalidData)?; + if _sync { + BorshSerialize::serialize(&len, writer) + } else { + BorshSerializeAsync::serialize(&len, writer).await + }?; for kv in vec { - kv.serialize(writer)?; + if _sync { + BorshSerialize::serialize(&kv, writer) + } else { + BorshSerializeAsync::serialize(&kv, writer).await + }?; } Ok(()) } } + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Ord + Sync, + H: BuildHasher + Sync, + )] impl BorshSerialize for HashSet where T: BorshSerialize + Ord, H: BuildHasher, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; let mut vec = self.iter().collect::>(); vec.sort(); - u32::try_from(vec.len()) - .map_err(|_| ErrorKind::InvalidData)? - .serialize(writer)?; + let len = u32::try_from(vec.len()).map_err(|_| ErrorKind::InvalidData)?; + if _sync { + BorshSerialize::serialize(&len, writer) + } else { + BorshSerializeAsync::serialize(&len, writer).await + }?; for item in vec { - item.serialize(writer)?; + if _sync { + BorshSerialize::serialize(&item, writer) + } else { + BorshSerializeAsync::serialize(&item, writer).await + }?; } Ok(()) } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + K: BorshSerializeAsync + Sync, + V: BorshSerializeAsync + Sync, +)] impl BorshSerialize for BTreeMap where K: BorshSerialize, V: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; // NOTE: BTreeMap iterates over the entries that are sorted by key, so the serialization // result will be consistent without a need to sort the entries as we do for HashMap // serialization. - u32::try_from(self.len()) - .map_err(|_| ErrorKind::InvalidData)? - .serialize(writer)?; + let len = u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?; + if _sync { + BorshSerialize::serialize(&len, writer) + } else { + BorshSerializeAsync::serialize(&len, writer).await + }?; for (key, value) in self { - key.serialize(writer)?; - value.serialize(writer)?; + if _sync { + BorshSerialize::serialize(&key, writer)?; + BorshSerialize::serialize(&value, writer) + } else { + BorshSerializeAsync::serialize(&key, writer).await?; + BorshSerializeAsync::serialize(&value, writer).await + }?; } Ok(()) } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, +)] impl BorshSerialize for BTreeSet where T: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; // NOTE: BTreeSet iterates over the items that are sorted, so the serialization result will // be consistent without a need to sort the entries as we do for HashSet serialization. - u32::try_from(self.len()) - .map_err(|_| ErrorKind::InvalidData)? - .serialize(writer)?; + let len = u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?; + if _sync { + BorshSerialize::serialize(&len, writer) + } else { + BorshSerializeAsync::serialize(&len, writer).await + }?; for item in self { - item.serialize(writer)?; + if _sync { + BorshSerialize::serialize(&item, writer) + } else { + BorshSerializeAsync::serialize(&item, writer).await + }?; } Ok(()) } } #[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for std::net::SocketAddr { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - match *self { - std::net::SocketAddr::V4(ref addr) => { - 0u8.serialize(writer)?; - addr.serialize(writer) + match self { + std::net::SocketAddr::V4(addr) => if _sync { + BorshSerialize::serialize(&0u8, writer)?; + BorshSerialize::serialize(addr, writer) + } else { + BorshSerializeAsync::serialize(&0u8, writer).await?; + BorshSerializeAsync::serialize(addr, writer).await } - std::net::SocketAddr::V6(ref addr) => { - 1u8.serialize(writer)?; - addr.serialize(writer) + std::net::SocketAddr::V6(addr) => if _sync { + BorshSerialize::serialize(&1u8, writer)?; + BorshSerialize::serialize(addr, writer) + } else { + BorshSerializeAsync::serialize(&1u8, writer).await?; + BorshSerializeAsync::serialize(addr, writer).await } } } } #[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for std::net::SocketAddrV4 { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.ip().serialize(writer)?; - self.port().serialize(writer) + if _sync { + BorshSerialize::serialize(self.ip(), writer)?; + BorshSerialize::serialize(&self.port(), writer) + } else { + BorshSerializeAsync::serialize(self.ip(), writer).await?; + BorshSerializeAsync::serialize(&self.port(), writer).await + } } } #[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for std::net::SocketAddrV6 { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.ip().serialize(writer)?; - self.port().serialize(writer) + if _sync { + BorshSerialize::serialize(self.ip(), writer)?; + BorshSerialize::serialize(&self.port(), writer) + } else { + BorshSerializeAsync::serialize(self.ip(), writer).await?; + BorshSerializeAsync::serialize(&self.port(), writer).await + } } } #[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for std::net::Ipv4Addr { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - writer.write_all(&self.octets()) + if _sync { + writer.write_all(&self.octets()) + } else { + writer.write_all(&self.octets()).await + } } } #[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for std::net::Ipv6Addr { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - writer.write_all(&self.octets()) + if _sync { + writer.write_all(&self.octets()) + } else { + writer.write_all(&self.octets()).await + } } } #[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait +)] impl BorshSerialize for std::net::IpAddr { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { match self { - std::net::IpAddr::V4(ipv4) => { + std::net::IpAddr::V4(ipv4) => if _sync { writer.write_all(&0u8.to_le_bytes())?; - ipv4.serialize(writer) + BorshSerialize::serialize(ipv4, writer) + } else { + writer.write_all(&0u8.to_le_bytes()).await?; + BorshSerializeAsync::serialize(ipv4, writer).await } - std::net::IpAddr::V6(ipv6) => { + std::net::IpAddr::V6(ipv6) => if _sync { writer.write_all(&1u8.to_le_bytes())?; - ipv6.serialize(writer) + BorshSerialize::serialize(ipv6, writer) + } else { + writer.write_all(&1u8.to_le_bytes()).await?; + BorshSerializeAsync::serialize(ipv6, writer).await } } } } + +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + ?Sized + Sync, +)] impl BorshSerialize for Box { + #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { - self.as_ref().serialize(writer) + let r#ref = self.as_ref(); + if _sync { + BorshSerialize::serialize(r#ref, writer) + } else { + BorshSerializeAsync::serialize(r#ref, writer).await + } } } +#[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + where + T: BorshSerializeAsync + Sync, +)] impl BorshSerialize for [T; N] where T: BorshSerialize, { #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { if N == 0 { - return Ok(()); + Ok(()) } else if let Some(u8_slice) = T::u8_slice(self) { - writer.write_all(u8_slice)?; + if _sync { + writer.write_all(u8_slice) + } else { + writer.write_all(u8_slice).await + } } else { for el in self.iter() { - el.serialize(writer)?; + if _sync { + BorshSerialize::serialize(el, writer) + } else { + BorshSerializeAsync::serialize(el, writer).await + }?; } + Ok(()) } - Ok(()) } } macro_rules! impl_tuple { (@unit $name:ty) => { + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait + )] impl BorshSerialize for $name { #[inline] + #[async_generic(async_signature(&self, _writer: &mut W) -> Result<()>)] fn serialize(&self, _writer: &mut W) -> Result<()> { Ok(()) } @@ -557,15 +1027,28 @@ macro_rules! impl_tuple { }; ($($idx:tt $name:ident)+) => { - impl<$($name),+> BorshSerialize for ($($name,)+) - where $($name: BorshSerialize,)+ - { - #[inline] - fn serialize(&self, writer: &mut W) -> Result<()> { - $(self.$idx.serialize(writer)?;)+ - Ok(()) + #[async_generic( + #[cfg(feature = "async")] + #[async_trait] + async_trait<$($name),+> + where + $($name: BorshSerializeAsync + Sync + Send,)+ + )] + impl<$($name),+> BorshSerialize for ($($name,)+) + where + $($name: BorshSerialize,)+ + { + #[inline] + #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + fn serialize(&self, writer: &mut W) -> Result<()> { + if _sync { + $(BorshSerialize::serialize(&self.$idx, writer)?;)+ + } else { + $(BorshSerializeAsync::serialize(&self.$idx, writer).await?;)+ + } + Ok(()) + } } - } }; } @@ -618,9 +1101,11 @@ pub mod rc { //! //! Module defines [BorshSerialize] implementation for //! [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). - use crate::__private::maybestd::{rc::Rc, sync::Arc}; - use crate::io::{Result, Write}; - use crate::BorshSerialize; + use crate::{ + __private::maybestd::{rc::Rc, sync::Arc}, + io::{Result, Write}, + BorshSerialize, + }; /// This impl requires the [`"rc"`] Cargo feature of borsh. /// From 447d7bb5cdcbacc41de6b1fc58df547dde22328c Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 22 Jan 2025 01:32:36 +0200 Subject: [PATCH 05/69] remove `async-generic` version --- borsh/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index fbccf4cc7..837fe14c8 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -41,7 +41,7 @@ hashbrown = { version = ">=0.11,<0.15.0", optional = true } bytes = { version = "1", optional = true } bson = { version = "2", optional = true } -async-generic = { git = "https://github.com/DanikVitek/async-generic.git", version = "2.0" } +async-generic = { git = "https://github.com/DanikVitek/async-generic.git" } async-trait = { version = "0.1", optional = true } tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } async-std = { version = "1", default-features = false, features = ["std"], optional = true } From 31a4c24f60af2f9596c61dc0a49f3a2262c7f0c9 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Thu, 23 Jan 2025 21:41:08 +0200 Subject: [PATCH 06/69] Remove dependency on sync counterparts --- borsh/src/de/mod.rs | 2 +- borsh/src/schema.rs | 2 +- borsh/src/ser/mod.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index a2ecd8d6a..98610bdea 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -41,7 +41,7 @@ const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending o #[async_generic( #[cfg(feature = "async")] #[async_trait] - async_trait: BorshDeserialize + async_trait )] pub trait BorshDeserialize: Sized { /// Deserializes this instance from a given slice of bytes. diff --git a/borsh/src/schema.rs b/borsh/src/schema.rs index 49bee3824..e9dad6350 100644 --- a/borsh/src/schema.rs +++ b/borsh/src/schema.rs @@ -12,7 +12,7 @@ //! * `BorshSchemaContainer` is used to store all declarations and definitions that are needed to work with a single type. #![allow(dead_code)] // Unclear why rust check complains on fields of `Definition` variants. -use crate as borsh; // For `#[derive(BorshSerialize, BorshDeserialize)]`. +use crate as borsh; // For `#[derive(BorshSerialize, BorshDeserialize, BorshSchema)]`. use crate::__private::maybestd::{ borrow, boxed::Box, diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 05e8913d4..bed4c12b7 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -58,7 +58,7 @@ const FLOAT_NAN_ERR: &str = "For portability reasons we do not allow to serializ #[async_generic( #[cfg(feature = "async")] #[async_trait] - async_trait: BorshSerialize + async_trait(copy_sync) )] pub trait BorshSerialize { #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] @@ -78,7 +78,7 @@ pub trait BorshSerialize { #[async_generic( #[cfg(feature = "async")] #[async_trait] - async_trait + async_trait(copy_sync) )] impl BorshSerialize for u8 { #[inline] From d484aa4d580f27d34328a4711b417c5530e1a5ed Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Mon, 27 Jan 2025 15:05:17 +0200 Subject: [PATCH 07/69] use `impl Future` for async traits --- Cargo.toml | 4 +- borsh/src/async_io.rs | 367 +++++++++++++++++++++++++++++--- borsh/src/de/mod.rs | 474 +++++++++++++++++++----------------------- 3 files changed, 562 insertions(+), 283 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 79d6b77e4..f098baa67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,5 @@ members = ["borsh", "borsh-derive", "fuzz/fuzz-run", "benchmarks"] [workspace.package] # shared version of all public crates in the workspace version = "1.5.5" -edition = "2018" -rust-version = "1.70.0" +edition = "2021" +rust-version = "1.75.0" diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index 5d6f4638f..3bf71c86c 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -1,61 +1,378 @@ -use async_trait::async_trait; +use core::future::Future; +use std::io::Result; -#[async_trait] +// use async_trait::async_trait; + +// #[async_trait] pub trait AsyncRead: Unpin + Send { - async fn read(&mut self, buf: &mut [u8]) -> std::io::Result; + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a; - async fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()>; + fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a; + + fn read_u8<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 1]; + self.read_exact(&mut buf).await?; + Ok(buf[0]) + } + } + + fn read_u16<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 2]; + self.read_exact(&mut buf).await?; + Ok(u16::from_le_bytes(buf)) + } + } + + fn read_u32<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 4]; + self.read_exact(&mut buf).await?; + Ok(u32::from_le_bytes(buf)) + } + } + + fn read_u64<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 8]; + self.read_exact(&mut buf).await?; + Ok(u64::from_le_bytes(buf)) + } + } + + fn read_u128<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 16]; + self.read_exact(&mut buf).await?; + Ok(u128::from_le_bytes(buf)) + } + } + + fn read_i8<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 1]; + self.read_exact(&mut buf).await?; + Ok(buf[0] as i8) + } + } + + fn read_i16<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 2]; + self.read_exact(&mut buf).await?; + Ok(i16::from_le_bytes(buf)) + } + } + + fn read_i32<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 4]; + self.read_exact(&mut buf).await?; + Ok(i32::from_le_bytes(buf)) + } + } + + fn read_i64<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 8]; + self.read_exact(&mut buf).await?; + Ok(i64::from_le_bytes(buf)) + } + } + + fn read_i128<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 16]; + self.read_exact(&mut buf).await?; + Ok(i128::from_le_bytes(buf)) + } + } + + fn read_f32<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 4]; + self.read_exact(&mut buf).await?; + Ok(f32::from_le_bytes(buf)) + } + } + + fn read_f64<'a>(&'a mut self) -> impl Future> + Send + 'a { + async { + let mut buf = [0u8; 8]; + self.read_exact(&mut buf).await?; + Ok(f64::from_le_bytes(buf)) + } + } } #[cfg(feature = "tokio")] -#[async_trait] +// #[async_trait] impl AsyncRead for R { #[inline] - async fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - tokio::io::AsyncReadExt::read(self, buf).await + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + 'a { + tokio::io::AsyncReadExt::read(self, buf) } #[inline] - async fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { - tokio::io::AsyncReadExt::read_exact(self, buf) - .await - .map(|_| ()) + fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { + async { + tokio::io::AsyncReadExt::read_exact(self, buf) + .await + .map(|_| ()) + } + } + + #[inline] + fn read_u8<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_u8(self) + } + + #[inline] + fn read_u16<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_u16_le(self) + } + + #[inline] + fn read_u32<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_u32_le(self) + } + + #[inline] + fn read_u64<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_u64_le(self) + } + + #[inline] + fn read_u128<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_u128_le(self) + } + + #[inline] + fn read_i8<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_i8(self) + } + + #[inline] + fn read_i16<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_i16_le(self) + } + + #[inline] + fn read_i32<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_i32_le(self) + } + + #[inline] + fn read_i64<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_i64_le(self) + } + + #[inline] + fn read_i128<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_i128_le(self) + } + + #[inline] + fn read_f32<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_f32_le(self) + } + + #[inline] + fn read_f64<'a>(&'a mut self) -> impl Future> + Send + 'a { + tokio::io::AsyncReadExt::read_f64_le(self) } } #[cfg(feature = "async-std")] -#[async_trait] +// #[async_trait] impl AsyncRead for R { #[inline] - async fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - async_std::io::ReadExt::read(self, buf).await + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { + async_std::io::ReadExt::read(self, buf) } #[inline] - async fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> { - async_std::io::ReadExt::read_exact(self, buf).await + fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { + async_std::io::ReadExt::read_exact(self, buf) } } -#[async_trait] +// #[async_trait] pub trait AsyncWrite: Unpin + Send { - async fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()>; + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a; + + fn write_u8<'a>(&'a mut self, n: u8) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_u16<'a>(&'a mut self, n: u16) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_u32<'a>(&'a mut self, n: u32) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_u64<'a>(&'a mut self, n: u64) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_u128<'a>(&'a mut self, n: u128) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_i8<'a>(&'a mut self, n: i8) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_i16<'a>(&'a mut self, n: i16) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_i32<'a>(&'a mut self, n: i32) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_i64<'a>(&'a mut self, n: i64) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_i128<'a>(&'a mut self, n: i128) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_f32<'a>(&'a mut self, n: f32) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } + + fn write_f64<'a>(&'a mut self, n: f64) -> impl Future> + Send + 'a { + async move { + let bytes = n.to_le_bytes(); + self.write_all(&bytes).await?; + Ok(()) + } + } } #[cfg(feature = "tokio")] -#[async_trait] +// #[async_trait] impl AsyncWrite for R { #[inline] - async fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { - tokio::io::AsyncWriteExt::write_all(self, buf).await + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_all(self, buf) + } + + #[inline] + fn write_u8<'a>(&'a mut self, n: u8) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_u8(self, n) + } + + #[inline] + fn write_u16<'a>(&'a mut self, n: u16) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_u16_le(self, n) + } + + #[inline] + fn write_u32<'a>(&'a mut self, n: u32) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_u32_le(self, n) + } + + #[inline] + fn write_u64<'a>(&'a mut self, n: u64) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_u64_le(self, n) + } + + #[inline] + fn write_u128<'a>(&'a mut self, n: u128) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_u128_le(self, n) + } + + #[inline] + fn write_i8<'a>(&'a mut self, n: i8) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_i8(self, n) + } + + #[inline] + fn write_i16<'a>(&'a mut self, n: i16) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_i16_le(self, n) + } + + #[inline] + fn write_i32<'a>(&'a mut self, n: i32) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_i32_le(self, n) + } + + #[inline] + fn write_i64<'a>(&'a mut self, n: i64) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_i64_le(self, n) + } + + #[inline] + fn write_i128<'a>(&'a mut self, n: i128) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_i128_le(self, n) + } + + #[inline] + fn write_f32<'a>(&'a mut self, n: f32) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_f32_le(self, n) + } + + #[inline] + fn write_f64<'a>(&'a mut self, n: f64) -> impl Future> + Send + 'a { + tokio::io::AsyncWriteExt::write_f64_le(self, n) } } #[cfg(feature = "async-std")] -#[async_trait] +// #[async_trait] impl AsyncWrite for R { #[inline] - async fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { - async_std::io::WriteExt::write_all(self, buf).await + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { + async_std::io::WriteExt::write_all(self, buf) } -} \ No newline at end of file +} diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 98610bdea..01a6a4a1d 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "async")] +use core::future::Future; use core::{ convert::{TryFrom, TryInto}, marker::PhantomData, @@ -5,11 +7,11 @@ use core::{ }; use async_generic::async_generic; -#[cfg(feature = "async")] -use async_trait::async_trait; #[cfg(feature = "bytes")] use bytes::{BufMut, BytesMut}; +#[cfg(feature = "async")] +use crate::async_io::AsyncRead; use crate::{ __private::maybestd::{ borrow::{Borrow, Cow, ToOwned}, @@ -23,8 +25,6 @@ use crate::{ error::check_zst, io::{Error, ErrorKind, Read, Result}, }; -#[cfg(feature = "async")] -use crate::async_io::AsyncRead; mod hint; @@ -40,8 +40,7 @@ const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending o /// A data-structure that can be de-serialized from binary format by NBOR. #[async_generic( #[cfg(feature = "async")] - #[async_trait] - async_trait + async_trait: Sized + Send )] pub trait BorshDeserialize: Sized { /// Deserializes this instance from a given slice of bytes. @@ -51,7 +50,7 @@ pub trait BorshDeserialize: Sized { } #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result; @@ -66,13 +65,13 @@ pub trait BorshDeserialize: Sized { } #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn try_from_reader(reader: &mut R) -> Result { let result = if _sync { - BorshDeserialize::deserialize_reader(reader) + Self::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + Self::deserialize_reader(reader).await }?; let mut buf = [0u8; 1]; @@ -86,7 +85,7 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] #[async_generic( - async_signature(len: u32, reader: &mut R) -> Result>> + async_signature[ready](len: u32, reader: &mut R) -> impl Future>>> + Send )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let _ = len; @@ -97,7 +96,7 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] #[async_generic( - async_signature(reader: &mut R) -> Result> + async_signature[ready](reader: &mut R) -> impl Future>> + Send )] fn array_from_reader(reader: &mut R) -> Result> { let _ = reader; @@ -108,8 +107,7 @@ pub trait BorshDeserialize: Sized { /// Additional methods offered on enums which is used by `[derive(BorshDeserialize)]`. #[async_generic( #[cfg(feature = "async")] - #[async_trait] - async_trait + async_trait: Sized + Send )] pub trait EnumExt: BorshDeserialize { /// Deserialises given variant of an enum from the reader. @@ -166,7 +164,7 @@ pub trait EnumExt: BorshDeserialize { /// assert!(from_slice::(&data[..]).is_err()); /// ``` #[async_generic( - async_signature(reader: &mut R, tag: u8) -> Result + async_signature[impl_fut](reader: &mut R, tag: u8) -> impl Future> + Send )] fn deserialize_variant(reader: &mut R, tag: u8) -> Result; } @@ -181,26 +179,27 @@ fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for u8 { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let mut buf = [0u8; 1]; - let result = reader.read_exact(&mut buf); - if _async { result.await } else { result } - .map_err(unexpected_eof_to_unexpected_length_of_input)?; - Ok(buf[0]) + if _sync { + let mut buf = [0u8; 1]; + reader.read_exact(&mut buf).map_err(unexpected_eof_to_unexpected_length_of_input)?; + Ok(buf[0]) + } else { + reader.read_u8() + } } #[inline] #[doc(hidden)] #[async_generic( - async_signature(len: u32, reader: &mut R) -> Result>> + async_signature[impl_fut](len: u32, reader: &mut R) -> impl Future>>> + Send )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let len: usize = len.try_into().map_err(|_| ErrorKind::InvalidData)?; @@ -236,7 +235,7 @@ impl BorshDeserialize for u8 { #[inline] #[doc(hidden)] #[async_generic( - async_signature(reader: &mut R) -> Result> + async_signature[impl_fut](reader: &mut R) -> impl Future>> + Send )] fn array_from_reader(reader: &mut R) -> Result> { let mut arr = [0u8; N]; @@ -248,56 +247,58 @@ impl BorshDeserialize for u8 { } macro_rules! impl_for_integer { - ($type: ident) => { + ($type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for $type { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let mut buf = [0u8; size_of::<$type>()]; - let res = reader.read_exact(&mut buf); - if _sync { res } else { res.await } - .map_err(unexpected_eof_to_unexpected_length_of_input)?; - let res = $type::from_le_bytes(buf.try_into().unwrap()); - Ok(res) + if _sync { + let mut buf = [0u8; size_of::<$type>()]; + reader + .read_exact(&mut buf) + .map_err(unexpected_eof_to_unexpected_length_of_input)?; + let res = $type::from_le_bytes(buf.try_into().unwrap()); + Ok(res) + } else { + reader.$method() + } } } }; } -impl_for_integer!(i8); -impl_for_integer!(i16); -impl_for_integer!(i32); -impl_for_integer!(i64); -impl_for_integer!(i128); -impl_for_integer!(u16); -impl_for_integer!(u32); -impl_for_integer!(u64); -impl_for_integer!(u128); +impl_for_integer!(i8, read_i8); +impl_for_integer!(i16, read_i16); +impl_for_integer!(i32, read_i32); +impl_for_integer!(i64, read_i64); +impl_for_integer!(i128, read_i128); +impl_for_integer!(u16, read_u16); +impl_for_integer!(u32, read_u32); +impl_for_integer!(u64, read_u64); +impl_for_integer!(u128, read_u128); macro_rules! impl_for_nonzero_integer { - ($type: ty) => { + ($type: ty, $repr: ty) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for $type { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { <$type>::new(if _sync { - BorshDeserialize::deserialize_reader(reader) + <$repr as BorshDeserialize>::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + <$repr as BorshDeserializeAsync>::deserialize_reader(reader).await }?) .ok_or_else(|| Error::new(ErrorKind::InvalidData, ERROR_INVALID_ZERO_VALUE)) } @@ -305,34 +306,34 @@ macro_rules! impl_for_nonzero_integer { }; } -impl_for_nonzero_integer!(core::num::NonZeroI8); -impl_for_nonzero_integer!(core::num::NonZeroI16); -impl_for_nonzero_integer!(core::num::NonZeroI32); -impl_for_nonzero_integer!(core::num::NonZeroI64); -impl_for_nonzero_integer!(core::num::NonZeroI128); -impl_for_nonzero_integer!(core::num::NonZeroU8); -impl_for_nonzero_integer!(core::num::NonZeroU16); -impl_for_nonzero_integer!(core::num::NonZeroU32); -impl_for_nonzero_integer!(core::num::NonZeroU64); -impl_for_nonzero_integer!(core::num::NonZeroU128); -impl_for_nonzero_integer!(core::num::NonZeroUsize); +impl_for_nonzero_integer!(core::num::NonZeroI8, i8); +impl_for_nonzero_integer!(core::num::NonZeroI16, i16); +impl_for_nonzero_integer!(core::num::NonZeroI32, i32); +impl_for_nonzero_integer!(core::num::NonZeroI64, i64); +impl_for_nonzero_integer!(core::num::NonZeroI128, i128); +impl_for_nonzero_integer!(core::num::NonZeroIsize, isize); +impl_for_nonzero_integer!(core::num::NonZeroU8, u8); +impl_for_nonzero_integer!(core::num::NonZeroU16, u16); +impl_for_nonzero_integer!(core::num::NonZeroU32, u32); +impl_for_nonzero_integer!(core::num::NonZeroU64, u64); +impl_for_nonzero_integer!(core::num::NonZeroU128, u128); +impl_for_nonzero_integer!(core::num::NonZeroUsize, usize); macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for $type { #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let i: $temp_type = if _sync { - BorshDeserialize::deserialize_reader(reader) + let i = if _sync { + <$temp_type as BorshDeserialize>::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + <$temp_type as BorshDeserializeAsync>::deserialize_reader(reader).await }?; let i = <$type>::try_from(i).map_err(|_| Error::new(ErrorKind::InvalidData, $msg))?; @@ -348,23 +349,26 @@ impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, // and vice versa. We disallow NaNs to avoid this issue. macro_rules! impl_for_float { - ($type: ident, $int_type: ident) => { + ($type: ident, $int_type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for $type { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let mut buf = [0u8; size_of::<$type>()]; - let res = reader.read_exact(&mut buf); - if _sync { res } else { res.await } - .map_err(unexpected_eof_to_unexpected_length_of_input)?; - let res = $type::from_bits($int_type::from_le_bytes(buf.try_into().unwrap())); + let res = if _sync { + let mut buf = [0u8; size_of::<$type>()]; + reader + .read_exact(&mut buf) + .map_err(unexpected_eof_to_unexpected_length_of_input)?; + $type::from_bits($int_type::from_le_bytes(buf.try_into().unwrap())) + } else { + reader.$method().await? + }; if res.is_nan() { return Err(Error::new( ErrorKind::InvalidData, @@ -377,40 +381,37 @@ macro_rules! impl_for_float { }; } -impl_for_float!(f32, u32); -impl_for_float!(f64, u64); +impl_for_float!(f32, u32, read_f32); +impl_for_float!(f64, u64, read_f64); #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for bool { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let b: u8 = if _sync { - BorshDeserialize::deserialize_reader(reader) + let b = if _sync { + ::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?; - if b == 0 { - Ok(false) - } else if b == 1 { - Ok(true) - } else { - let msg = format!("Invalid bool representation: {}", b); - - Err(Error::new(ErrorKind::InvalidData, msg)) + match b { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(Error::new( + ErrorKind::InvalidData, + format!("Invalid bool representation: {}", b), + )), } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where T: BorshDeserializeAsync, @@ -421,13 +422,13 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let flag: u8 = if _sync { - BorshDeserialize::deserialize_reader(reader) + let flag = if _sync { + ::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?; match flag { 0 => Ok(None), @@ -450,7 +451,6 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where T: BorshDeserializeAsync, @@ -463,13 +463,13 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let flag: u8 = if _sync { - BorshDeserialize::deserialize_reader(reader) + let flag = if _sync { + ::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + ::deserialize_reader(reader).await }?; match flag { 0 => Ok(Err(if _sync { @@ -496,13 +496,12 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for String { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { String::from_utf8(if _sync { @@ -524,9 +523,10 @@ pub mod ascii { //! Module defines [BorshDeserialize] implementation for //! some types from [ascii](::ascii) crate. - use async_generic::async_generic; #[cfg(feature = "async")] - use async_trait::async_trait; + use core::future::Future; + + use async_generic::async_generic; use super::BorshDeserialize; #[cfg(feature = "async")] @@ -538,13 +538,12 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for ascii::AsciiString { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let bytes = if _sync { @@ -559,13 +558,12 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for ascii::AsciiChar { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let byte = if _sync { @@ -581,10 +579,9 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshDeserializeAsync + Send, + T: BorshDeserializeAsync, )] impl BorshDeserialize for Vec where @@ -592,7 +589,7 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; @@ -605,9 +602,9 @@ where if len == 0 { Ok(Vec::new()) } else if let Some(vec_bytes) = if _sync { - ::vec_from_reader(len, reader) + T::vec_from_reader(len, reader) } else { - ::vec_from_reader(len, reader).await + T::vec_from_reader(len, reader).await }? { Ok(vec_bytes) } else { @@ -615,9 +612,9 @@ where let mut result = Vec::with_capacity(hint::cautious::(len)); for _ in 0..len { result.push(if _sync { - ::deserialize_reader(reader) + T::deserialize_reader(reader) } else { - ::deserialize_reader(reader).await + T::deserialize_reader(reader).await }?); } Ok(result) @@ -628,13 +625,12 @@ where #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for bytes::Bytes { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { @@ -649,13 +645,12 @@ impl BorshDeserialize for bytes::Bytes { #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for BytesMut { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let len = if _sync { @@ -678,13 +673,12 @@ impl BorshDeserialize for BytesMut { #[cfg(feature = "bson")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for bson::oid::ObjectId { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 12]; @@ -699,11 +693,11 @@ impl BorshDeserialize for bson::oid::ObjectId { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where T: ToOwned + ?Sized, T::Owned: BorshDeserializeAsync, + for<'a> &'a T: Send, )] impl BorshDeserialize for Cow<'_, T> where @@ -712,23 +706,22 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { Ok(Cow::Owned(if _sync { - BorshDeserialize::deserialize_reader(reader) + T::Owned::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + T::Owned::deserialize_reader(reader).await }?)) } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshDeserializeAsync + Send, + T: BorshDeserializeAsync, )] impl BorshDeserialize for VecDeque where @@ -736,13 +729,13 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { - as BorshDeserialize>::deserialize_reader(reader) + >::deserialize_reader(reader) } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await + >::deserialize_reader(reader).await }?; Ok(vec.into()) } @@ -750,10 +743,9 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshDeserializeAsync + Send, + T: BorshDeserializeAsync, )] impl BorshDeserialize for LinkedList where @@ -761,13 +753,13 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { - as BorshDeserialize>::deserialize_reader(reader) + >::deserialize_reader(reader) } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await + >::deserialize_reader(reader).await }?; Ok(vec.into_iter().collect::>()) } @@ -779,11 +771,11 @@ where /// [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { + #[cfg(feature = "async")] + use core::future::Future; use core::hash::{BuildHasher, Hash}; use async_generic::async_generic; - #[cfg(feature = "async")] - use async_trait::async_trait; use super::BorshDeserialize; #[cfg(feature = "async")] @@ -803,12 +795,11 @@ pub mod hashes { const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order"; #[async_generic( - #[cfg(feature = "async")] - #[async_trait] + #[cfg(feature = "async")] async_trait where - T: BorshDeserializeAsync + Eq + Hash + Ord + Send, - H: BuildHasher + Default, + T: BorshDeserializeAsync + Eq + Hash + Ord, + H: BuildHasher + Default + Send, )] impl BorshDeserialize for HashSet where @@ -817,7 +808,7 @@ pub mod hashes { { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense @@ -825,9 +816,9 @@ pub mod hashes { // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster let vec = if _sync { - as BorshDeserialize>::deserialize_reader(reader) + >::deserialize_reader(reader) } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await + >::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -852,12 +843,11 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - K: BorshDeserializeAsync + Eq + Hash + Ord + Send, - V: BorshDeserializeAsync + Send, - H: BuildHasher + Default, + K: BorshDeserializeAsync + Eq + Hash + Ord, + V: BorshDeserializeAsync, + H: BuildHasher + Default + Send, )] impl BorshDeserialize for HashMap where @@ -867,7 +857,7 @@ pub mod hashes { { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; @@ -876,9 +866,9 @@ pub mod hashes { // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster let vec = if _sync { - as BorshDeserialize>::deserialize_reader(reader) + >::deserialize_reader(reader) } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await + >::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -904,10 +894,9 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshDeserializeAsync + Ord + Send, + T: BorshDeserializeAsync + Ord, )] impl BorshDeserialize for BTreeSet where @@ -915,7 +904,7 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense @@ -923,9 +912,9 @@ where // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster let vec = if _sync { - as BorshDeserialize>::deserialize_reader(reader) + >::deserialize_reader(reader) } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await + >::deserialize_reader(reader).await }?; #[cfg(feature = "de_strict_order")] @@ -951,11 +940,10 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - K: BorshDeserializeAsync + Ord + Send, - V: BorshDeserializeAsync + Send, + K: BorshDeserializeAsync + Ord, + V: BorshDeserializeAsync, )] impl BorshDeserialize for BTreeMap where @@ -964,7 +952,7 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; @@ -1003,13 +991,12 @@ where #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for std::net::SocketAddr { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let kind = if _sync { @@ -1041,13 +1028,12 @@ impl BorshDeserialize for std::net::SocketAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for std::net::IpAddr { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let kind = if _sync { @@ -1056,24 +1042,18 @@ impl BorshDeserialize for std::net::IpAddr { ::deserialize_reader(reader).await }?; match kind { - 0 => { - // Deserialize an Ipv4Addr and convert it to IpAddr::V4 - let ipv4_addr = if _sync { - ::deserialize_reader(reader) - } else { - ::deserialize_reader(reader).await - }?; - Ok(std::net::IpAddr::V4(ipv4_addr)) + 0 => if _sync { + ::deserialize_reader(reader) + } else { + ::deserialize_reader(reader).await } - 1 => { - // Deserialize an Ipv6Addr and convert it to IpAddr::V6 - let ipv6_addr = if _sync { - ::deserialize_reader(reader) - } else { - ::deserialize_reader(reader).await - }?; - Ok(std::net::IpAddr::V6(ipv6_addr)) + .map(std::net::IpAddr::V4), + 1 => if _sync { + ::deserialize_reader(reader) + } else { + ::deserialize_reader(reader).await } + .map(std::net::IpAddr::V6), value => Err(Error::new( ErrorKind::InvalidData, format!("Invalid IpAddr variant: {}", value), @@ -1085,13 +1065,12 @@ impl BorshDeserialize for std::net::IpAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for std::net::SocketAddrV4 { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { @@ -1111,13 +1090,12 @@ impl BorshDeserialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for std::net::SocketAddrV6 { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { @@ -1137,13 +1115,12 @@ impl BorshDeserialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for std::net::Ipv4Addr { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 4]; @@ -1157,13 +1134,12 @@ impl BorshDeserialize for std::net::Ipv4Addr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for std::net::Ipv6Addr { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 16]; @@ -1176,11 +1152,10 @@ impl BorshDeserialize for std::net::Ipv6Addr { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where U: Into> + Borrow, - T: ToOwned + ?Sized, + T: ToOwned + ?Sized + Send, T::Owned: BorshDeserializeAsync, )] impl BorshDeserialize for Box @@ -1191,7 +1166,7 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { @@ -1262,10 +1237,9 @@ where } #[cfg(feature = "async")] -#[async_trait] impl BorshDeserializeAsync for [T; N] where - T: BorshDeserializeAsync + Send, + T: BorshDeserializeAsync, { #[inline] async fn deserialize_reader(reader: &mut R) -> Result { @@ -1302,14 +1276,16 @@ where // TODO: replace with `core::array::try_from_fn` when stabilized to avoid manually // dropping uninitialized values through the guard drop. for elem in self.buffer.iter_mut() { - elem.write(::deserialize_reader(self.reader).await?); + elem.write( + T::deserialize_reader(self.reader).await?, + ); self.init_count += 1; } Ok(()) } } - if let Some(arr) = ::array_from_reader(reader).await? { + if let Some(arr) = T::array_from_reader(reader).await? { Ok(arr) } else { let mut result = ArrayDropGuard { @@ -1338,12 +1314,11 @@ fn array_deserialization_doesnt_leak() { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for MyType { #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { let val = if _sync { @@ -1388,15 +1363,14 @@ macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshDeserialize for $name { #[inline] #[async_generic( - async_signature(_reader: &mut R) -> Result + async_signature[ready](_: &mut R) -> impl Future> + Send )] - fn deserialize_reader(_reader: &mut R) -> Result { + fn deserialize_reader(_: &mut R) -> Result { Ok(<$name>::default()) } } @@ -1405,10 +1379,9 @@ macro_rules! impl_tuple { ($($name:ident)+) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait<$($name),+> where - $($name: BorshDeserializeAsync + Send,)+ + $($name: BorshDeserializeAsync,)+ )] impl<$($name),+> BorshDeserialize for ($($name,)+) where @@ -1416,7 +1389,7 @@ macro_rules! impl_tuple { { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { @@ -1454,22 +1427,23 @@ impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18); impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19); macro_rules! impl_range { - ($type:ident, $make:expr, $($side:ident),*) => { + ($type:ident, $make:expr, $n: literal, $($side:ident),*) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] - async_trait + async_trait + where + T: BorshDeserializeAsync, )] impl BorshDeserialize for core::ops::$type { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { - let ($($side,)*) = if _sync { - BorshDeserialize::deserialize_reader(reader) + let [$($side,)*] = if _sync { + <[T; $n] as BorshDeserialize>::deserialize_reader(reader) } else { - BorshDeserializeAsync::deserialize_reader(reader).await + <[T; $n] as BorshDeserializeAsync>::deserialize_reader(reader).await }?; Ok($make) } @@ -1477,11 +1451,11 @@ macro_rules! impl_range { }; } -impl_range!(Range, start..end, start, end); -impl_range!(RangeInclusive, start..=end, start, end); -impl_range!(RangeFrom, start.., start); -impl_range!(RangeTo, ..end, end); -impl_range!(RangeToInclusive, ..=end, end); +impl_range!(Range, start..end, 2, start, end); +impl_range!(RangeInclusive, start..=end, 2, start, end); +impl_range!(RangeFrom, start.., 1, start); +impl_range!(RangeTo, ..end, 1, end); +impl_range!(RangeToInclusive, ..=end, 1, end); /// Module is available if borsh is built with `features = ["rc"]`. #[cfg(feature = "rc")] @@ -1490,9 +1464,10 @@ pub mod rc { //! Module defines [BorshDeserialize] implementation for //! [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). - use async_generic::async_generic; #[cfg(feature = "async")] - use async_trait::async_trait; + use core::future::Future; + + use async_generic::async_generic; use super::BorshDeserialize; #[cfg(feature = "async")] @@ -1507,27 +1482,26 @@ pub mod rc { /// Deserializing a data structure containing `Rc` will not attempt to /// deduplicate `Rc` references to the same data. Every deserialized `Rc` /// will end up with a strong count of 1. - #[async_generic( - #[cfg(feature = "async")] - #[async_trait] - async_trait - where - Box: BorshDeserializeAsync, - )] + // #[async_generic( + // #[cfg(feature = "async")] + // async_trait + // where + // Box: BorshDeserializeAsync, + // )] impl BorshDeserialize for Rc where Box: BorshDeserialize, { #[inline] - #[async_generic( - async_signature(reader: &mut R) -> Result - )] + // #[async_generic( + // async_signature[impl_fut](reader: &mut R) -> impl Future> + Send + // )] fn deserialize_reader(reader: &mut R) -> Result { - Ok(if _sync { - as BorshDeserialize>::deserialize_reader(reader) - } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await - }? + Ok(//if _sync { + >::deserialize_reader(reader) + // } else { + // >::deserialize_reader(reader).await + /*}*/? .into()) } } @@ -1539,10 +1513,10 @@ pub mod rc { /// will end up with a strong count of 1. #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where Box: BorshDeserializeAsync, + Self: Send, )] impl BorshDeserialize for Arc where @@ -1550,13 +1524,13 @@ pub mod rc { { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { - as BorshDeserialize>::deserialize_reader(reader) + >::deserialize_reader(reader) } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await + >::deserialize_reader(reader).await }? .into()) } @@ -1565,13 +1539,12 @@ pub mod rc { #[async_generic( #[cfg(feature = "async")] - #[async_trait] - async_trait + async_trait )] impl BorshDeserialize for PhantomData { #[inline] #[async_generic( - async_signature(_: &mut R) -> Result + async_signature[ready](_: &mut R) -> impl Future> + Send )] fn deserialize_reader(_: &mut R) -> Result { Ok(PhantomData) @@ -1580,7 +1553,6 @@ impl BorshDeserialize for PhantomData { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where T: BorshDeserializeAsync + Copy, @@ -1591,13 +1563,13 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { if _sync { - ::deserialize_reader(reader) + T::deserialize_reader(reader) } else { - ::deserialize_reader(reader).await + T::deserialize_reader(reader).await } .map(core::cell::Cell::new) } @@ -1605,7 +1577,6 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where T: BorshDeserializeAsync, @@ -1616,13 +1587,13 @@ where { #[inline] #[async_generic( - async_signature(reader: &mut R) -> Result + async_signature[impl_fut](reader: &mut R) -> impl Future> + Send )] fn deserialize_reader(reader: &mut R) -> Result { if _sync { - ::deserialize_reader(reader) + T::deserialize_reader(reader) } else { - ::deserialize_reader(reader).await + T::deserialize_reader(reader).await } .map(core::cell::RefCell::new) } @@ -1689,21 +1660,12 @@ pub fn from_slice(v: &[u8]) -> Result { /// ``` #[async_generic( #[cfg(feature = "async")] - async_signature(reader: &mut R) -> Result + async_signature[impl_fut]<'a, R: AsyncRead, T: BorshDeserializeAsync + 'a>(reader: &'a mut R) -> impl Future> + Send + 'a )] pub fn from_reader(reader: &mut R) -> Result { - let result = if _sync { - ::deserialize_reader(reader) - } else { - ::deserialize_reader(reader).await - }?; - let mut buf = [0u8; 1]; - match if _sync { - reader.read_exact(&mut buf) + if _sync { + T::try_from_reader(reader) } else { - reader.read_exact(&mut buf).await - } { - Err(f) if f.kind() == ErrorKind::UnexpectedEof => Ok(result), - _ => Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)), + T::try_from_reader(reader) } } From a2526e21c170edb4ff6b8398fa17d352484ac387 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 00:34:04 +0200 Subject: [PATCH 08/69] Implement async traits, using `impl Future` --- borsh/Cargo.toml | 3 +- borsh/src/async_io.rs | 92 ++++---- borsh/src/ser/mod.rs | 512 ++++++++++++++++++++++++------------------ 3 files changed, 341 insertions(+), 266 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 3d15fc160..41b815a0e 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -42,7 +42,6 @@ bytes = { version = "1", optional = true } bson = { version = "2", optional = true } async-generic = { git = "https://github.com/DanikVitek/async-generic.git" } -async-trait = { version = "0.1", optional = true } tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } async-std = { version = "1", default-features = false, features = ["std"], optional = true } @@ -57,7 +56,7 @@ targets = ["x86_64-unknown-linux-gnu"] [features] default = ["std"] derive = ["borsh-derive"] -async = ["dep:async-trait"] +async = [] tokio = ["async", "dep:tokio"] async-std = ["async", "dep:async-std"] unstable__schema = ["derive", "borsh-derive/schema"] diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index 3bf71c86c..b8e3a2489 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -8,7 +8,7 @@ pub trait AsyncRead: Unpin + Send { fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a; fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a; - + fn read_u8<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 1]; @@ -16,7 +16,7 @@ pub trait AsyncRead: Unpin + Send { Ok(buf[0]) } } - + fn read_u16<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 2]; @@ -24,7 +24,7 @@ pub trait AsyncRead: Unpin + Send { Ok(u16::from_le_bytes(buf)) } } - + fn read_u32<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 4]; @@ -32,7 +32,7 @@ pub trait AsyncRead: Unpin + Send { Ok(u32::from_le_bytes(buf)) } } - + fn read_u64<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 8]; @@ -40,7 +40,7 @@ pub trait AsyncRead: Unpin + Send { Ok(u64::from_le_bytes(buf)) } } - + fn read_u128<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 16]; @@ -48,7 +48,7 @@ pub trait AsyncRead: Unpin + Send { Ok(u128::from_le_bytes(buf)) } } - + fn read_i8<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 1]; @@ -56,7 +56,7 @@ pub trait AsyncRead: Unpin + Send { Ok(buf[0] as i8) } } - + fn read_i16<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 2]; @@ -64,7 +64,7 @@ pub trait AsyncRead: Unpin + Send { Ok(i16::from_le_bytes(buf)) } } - + fn read_i32<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 4]; @@ -72,7 +72,7 @@ pub trait AsyncRead: Unpin + Send { Ok(i32::from_le_bytes(buf)) } } - + fn read_i64<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 8]; @@ -80,7 +80,7 @@ pub trait AsyncRead: Unpin + Send { Ok(i64::from_le_bytes(buf)) } } - + fn read_i128<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 16]; @@ -88,7 +88,7 @@ pub trait AsyncRead: Unpin + Send { Ok(i128::from_le_bytes(buf)) } } - + fn read_f32<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 4]; @@ -96,7 +96,7 @@ pub trait AsyncRead: Unpin + Send { Ok(f32::from_le_bytes(buf)) } } - + fn read_f64<'a>(&'a mut self) -> impl Future> + Send + 'a { async { let mut buf = [0u8; 8]; @@ -122,62 +122,62 @@ impl AsyncRead for R { .map(|_| ()) } } - + #[inline] fn read_u8<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_u8(self) } - + #[inline] fn read_u16<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_u16_le(self) } - + #[inline] fn read_u32<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_u32_le(self) } - + #[inline] fn read_u64<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_u64_le(self) } - + #[inline] fn read_u128<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_u128_le(self) } - + #[inline] fn read_i8<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_i8(self) } - + #[inline] fn read_i16<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_i16_le(self) } - + #[inline] fn read_i32<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_i32_le(self) } - + #[inline] fn read_i64<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_i64_le(self) } - + #[inline] fn read_i128<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_i128_le(self) } - + #[inline] fn read_f32<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_f32_le(self) } - + #[inline] fn read_f64<'a>(&'a mut self) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read_f64_le(self) @@ -217,7 +217,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_u32<'a>(&'a mut self, n: u32) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -225,7 +225,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_u64<'a>(&'a mut self, n: u64) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -233,7 +233,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_u128<'a>(&'a mut self, n: u128) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -241,7 +241,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_i8<'a>(&'a mut self, n: i8) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -249,7 +249,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_i16<'a>(&'a mut self, n: i16) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -257,7 +257,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_i32<'a>(&'a mut self, n: i32) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -265,7 +265,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_i64<'a>(&'a mut self, n: i64) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -273,7 +273,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_i128<'a>(&'a mut self, n: i128) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -281,7 +281,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_f32<'a>(&'a mut self, n: f32) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -289,7 +289,7 @@ pub trait AsyncWrite: Unpin + Send { Ok(()) } } - + fn write_f64<'a>(&'a mut self, n: f64) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); @@ -306,62 +306,62 @@ impl AsyncWrite for R { fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_all(self, buf) } - + #[inline] fn write_u8<'a>(&'a mut self, n: u8) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_u8(self, n) } - + #[inline] fn write_u16<'a>(&'a mut self, n: u16) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_u16_le(self, n) } - + #[inline] fn write_u32<'a>(&'a mut self, n: u32) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_u32_le(self, n) } - + #[inline] fn write_u64<'a>(&'a mut self, n: u64) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_u64_le(self, n) } - + #[inline] fn write_u128<'a>(&'a mut self, n: u128) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_u128_le(self, n) } - + #[inline] fn write_i8<'a>(&'a mut self, n: i8) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_i8(self, n) } - + #[inline] fn write_i16<'a>(&'a mut self, n: i16) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_i16_le(self, n) } - + #[inline] fn write_i32<'a>(&'a mut self, n: i32) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_i32_le(self, n) } - + #[inline] fn write_i64<'a>(&'a mut self, n: i64) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_i64_le(self, n) } - + #[inline] fn write_i128<'a>(&'a mut self, n: i128) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_i128_le(self, n) } - + #[inline] fn write_f32<'a>(&'a mut self, n: f32) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_f32_le(self, n) } - + #[inline] fn write_f64<'a>(&'a mut self, n: f64) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_f64_le(self, n) diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index bed4c12b7..b0e82a574 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -1,8 +1,8 @@ +#[cfg(feature = "async")] +use core::future::Future; use core::{convert::TryFrom, marker::PhantomData}; use async_generic::async_generic; -#[cfg(feature = "async")] -use async_trait::async_trait; #[cfg(feature = "async")] use crate::async_io::AsyncWrite; @@ -57,11 +57,12 @@ const FLOAT_NAN_ERR: &str = "For portability reasons we do not allow to serializ /// ``` #[async_generic( #[cfg(feature = "async")] - #[async_trait] - async_trait(copy_sync) + async_trait(copy_sync): Sync )] pub trait BorshSerialize { - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()>; #[inline] @@ -77,18 +78,18 @@ pub trait BorshSerialize { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait(copy_sync) )] impl BorshSerialize for u8 { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { - let res = writer.write_all(core::slice::from_ref(self)); if _sync { - res + writer.write_all(core::slice::from_ref(self)) } else { - res.await + writer.write_u8(*self) } } @@ -99,180 +100,192 @@ impl BorshSerialize for u8 { } macro_rules! impl_for_integer { - ($type: ident) => { + ($type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for $type { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { - let bytes = self.to_le_bytes(); if _sync { + let bytes = self.to_le_bytes(); writer.write_all(&bytes) } else { - writer.write_all(&bytes).await + writer.$method(*self) } } } }; } -impl_for_integer!(i8); -impl_for_integer!(i16); -impl_for_integer!(i32); -impl_for_integer!(i64); -impl_for_integer!(i128); -impl_for_integer!(u16); -impl_for_integer!(u32); -impl_for_integer!(u64); -impl_for_integer!(u128); +impl_for_integer!(i8, write_i8); +impl_for_integer!(i16, write_i16); +impl_for_integer!(i32, write_i32); +impl_for_integer!(i64, write_i64); +impl_for_integer!(i128, write_i128); +impl_for_integer!(u16, write_u16); +impl_for_integer!(u32, write_u32); +impl_for_integer!(u64, write_u64); +impl_for_integer!(u128, write_u128); macro_rules! impl_for_nonzero_integer { - ($type: ty) => { + ($type: ty, $method: ident $(, $repr: ty)?) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for $type { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { BorshSerialize::serialize(&self.get(), writer) } else { - BorshSerializeAsync::serialize(&self.get(), writer).await + let value = self.get(); + writer.$method(value $(as $repr)?) } } } }; } -impl_for_nonzero_integer!(core::num::NonZeroI8); -impl_for_nonzero_integer!(core::num::NonZeroI16); -impl_for_nonzero_integer!(core::num::NonZeroI32); -impl_for_nonzero_integer!(core::num::NonZeroI64); -impl_for_nonzero_integer!(core::num::NonZeroI128); -impl_for_nonzero_integer!(core::num::NonZeroU8); -impl_for_nonzero_integer!(core::num::NonZeroU16); -impl_for_nonzero_integer!(core::num::NonZeroU32); -impl_for_nonzero_integer!(core::num::NonZeroU64); -impl_for_nonzero_integer!(core::num::NonZeroU128); -impl_for_nonzero_integer!(core::num::NonZeroUsize); +impl_for_nonzero_integer!(core::num::NonZeroI8, write_i8); +impl_for_nonzero_integer!(core::num::NonZeroI16, write_i16); +impl_for_nonzero_integer!(core::num::NonZeroI32, write_i32); +impl_for_nonzero_integer!(core::num::NonZeroI64, write_i64); +impl_for_nonzero_integer!(core::num::NonZeroI128, write_i128); +impl_for_nonzero_integer!(core::num::NonZeroIsize, write_i64, i64); +impl_for_nonzero_integer!(core::num::NonZeroU8, write_u8); +impl_for_nonzero_integer!(core::num::NonZeroU16, write_u16); +impl_for_nonzero_integer!(core::num::NonZeroU32, write_u32); +impl_for_nonzero_integer!(core::num::NonZeroU64, write_u64); +impl_for_nonzero_integer!(core::num::NonZeroU128, write_u128); +impl_for_nonzero_integer!(core::num::NonZeroUsize, write_u64, u64); macro_rules! impl_for_size_integer { - ($type:ty: $repr:ty) => { + ($type:ty: $repr:ty, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for $type { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { BorshSerialize::serialize(&(*self as $repr), writer) } else { - BorshSerializeAsync::serialize(&(*self as $repr), writer).await + let value = *self as $repr; + writer.$method(value) } } } }; } -impl_for_size_integer!(usize: u64); -impl_for_size_integer!(isize: i64); +impl_for_size_integer!(usize: u64, write_u64); +impl_for_size_integer!(isize: i64, write_i64); // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, // and vice-versa. We disallow NaNs to avoid this issue. macro_rules! impl_for_float { - ($type: ident) => { + ($type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for $type { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if self.is_nan() { return Err(Error::new(ErrorKind::InvalidData, FLOAT_NAN_ERR)); } - let bytes = self.to_bits().to_le_bytes(); - if _sync { + if _sync{ + let bytes = self.to_bits().to_le_bytes(); writer.write_all(&bytes) } else { - writer.write_all(&bytes).await + writer.$method(*self).await } } } }; } -impl_for_float!(f32); -impl_for_float!(f64); +impl_for_float!(f32, write_f32); +impl_for_float!(f64, write_f64); #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for bool { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let byte = u8::from(*self); if _sync { BorshSerialize::serialize(&byte, writer) } else { - BorshSerializeAsync::serialize(&byte, writer).await + writer.write_u8(byte) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + Sync, + T: BorshSerializeAsync, )] impl BorshSerialize for Option where T: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { match self { - None => if _sync { - BorshSerialize::serialize(&0u8, writer) - } else { - BorshSerializeAsync::serialize(&0u8, writer).await - }, - Some(value) => if _sync { - BorshSerialize::serialize(&1u8, writer)?; - BorshSerialize::serialize(value, writer) - } else { - BorshSerializeAsync::serialize(&1u8, writer).await?; - BorshSerializeAsync::serialize(value, writer).await - }, + None => { + if _sync { + BorshSerialize::serialize(&0u8, writer) + } else { + BorshSerializeAsync::serialize(&0u8, writer).await + } + } + Some(value) => { + if _sync { + BorshSerialize::serialize(&1u8, writer)?; + BorshSerialize::serialize(value, writer) + } else { + BorshSerializeAsync::serialize(&1u8, writer).await?; + BorshSerializeAsync::serialize(value, writer).await + } + } } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + Sync, - E: BorshSerializeAsync + Sync, + T: BorshSerializeAsync, + E: BorshSerializeAsync, )] impl BorshSerialize for core::result::Result where @@ -280,22 +293,28 @@ where E: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { match self { - Err(e) => if _sync { - BorshSerialize::serialize(&0u8, writer)?; - BorshSerialize::serialize(e, writer) - } else { - BorshSerializeAsync::serialize(&0u8, writer).await?; - BorshSerializeAsync::serialize(e, writer).await + Err(e) => { + if _sync { + BorshSerialize::serialize(&0u8, writer)?; + BorshSerialize::serialize(e, writer) + } else { + BorshSerializeAsync::serialize(&0u8, writer).await?; + BorshSerializeAsync::serialize(e, writer).await + } } - Ok(v) => if _sync { - BorshSerialize::serialize(&1u8, writer)?; - BorshSerialize::serialize(v, writer) - } else { - BorshSerializeAsync::serialize(&1u8, writer).await?; - BorshSerializeAsync::serialize(v, writer).await + Ok(v) => { + if _sync { + BorshSerialize::serialize(&1u8, writer)?; + BorshSerialize::serialize(v, writer) + } else { + BorshSerializeAsync::serialize(&1u8, writer).await?; + BorshSerializeAsync::serialize(v, writer).await + } } } } @@ -303,36 +322,37 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for str { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_bytes(); if _sync { BorshSerialize::serialize(bytes, writer) } else { - BorshSerializeAsync::serialize(bytes, writer).await + BorshSerializeAsync::serialize(bytes, writer) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for String { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { - let bytes = self.as_bytes(); if _sync { - BorshSerialize::serialize(bytes, writer) + BorshSerialize::serialize(&**self, writer) } else { - BorshSerializeAsync::serialize(bytes, writer).await + BorshSerializeAsync::serialize(&**self, writer) } } } @@ -344,9 +364,10 @@ pub mod ascii { //! Module defines [BorshSerialize] implementation for //! some types from [ascii](::ascii) crate. - use async_generic::async_generic; #[cfg(feature = "async")] - use async_trait::async_trait; + use core::future::Future; + + use async_generic::async_generic; use super::BorshSerialize; #[cfg(feature = "async")] @@ -355,54 +376,56 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for ascii::AsciiChar { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let byte = self.as_byte(); if _sync { BorshSerialize::serialize(&byte, writer) } else { - BorshSerializeAsync::serialize(&byte, writer).await + writer.write_u8(byte) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for ascii::AsciiStr { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_bytes(); if _sync { BorshSerialize::serialize(bytes, writer) } else { - BorshSerializeAsync::serialize(bytes, writer).await + BorshSerializeAsync::serialize(bytes, writer) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for ascii::AsciiString { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { - let bytes = self.as_bytes(); if _sync { - BorshSerialize::serialize(bytes, writer) + BorshSerialize::serialize(&**self, writer) } else { - BorshSerializeAsync::serialize(bytes, writer).await + BorshSerializeAsync::serialize(&**self, writer) } } } @@ -438,7 +461,6 @@ fn serialize_slice(data: &[T], writer: &mut W) -> R #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where T: BorshSerializeAsync + Sync, @@ -448,14 +470,18 @@ where T: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { - let bytes = (u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(); + let len = u32::try_from(self.len()) + .map_err(|_| ErrorKind::InvalidData)? + .to_le_bytes(); if _sync { - writer.write_all(&bytes)?; + writer.write_all(&len)?; serialize_slice(self, writer) } else { - writer.write_all(&bytes).await?; + writer.write_all(&len).await?; serialize_slice_async(self, writer).await } } @@ -463,27 +489,27 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for &T { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { BorshSerialize::serialize(*self, writer) } else { - BorshSerializeAsync::serialize(*self, writer).await + BorshSerializeAsync::serialize(*self, writer) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + ToOwned + ?Sized + Sync, + T: BorshSerializeAsync + ToOwned + ?Sized, ::Owned: Sync, )] impl BorshSerialize for Cow<'_, T> @@ -491,37 +517,42 @@ where T: BorshSerialize + ToOwned + ?Sized, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let r#ref = self.as_ref(); if _sync { BorshSerialize::serialize(r#ref, writer) } else { - BorshSerializeAsync::serialize(r#ref, writer).await + BorshSerializeAsync::serialize(r#ref, writer) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + Sync, + T: BorshSerializeAsync, )] impl BorshSerialize for Vec where T: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; - let slice = self.as_slice(); if _sync { BorshSerialize::serialize(slice, writer) } else { + // don't remove `.await`, because `async_signature` will remove the implicit `async` + // block and you would need to setup the state machine manually anyway, + // because of `?` in `check_zst::()?` BorshSerializeAsync::serialize(slice, writer).await } } @@ -530,18 +561,19 @@ where #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for bytes::Bytes { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_ref(); if _sync { BorshSerialize::serialize(bytes, writer) } else { - BorshSerializeAsync::serialize(bytes, writer).await + BorshSerializeAsync::serialize(bytes, writer) } } } @@ -549,54 +581,62 @@ impl BorshSerialize for bytes::Bytes { #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for bytes::BytesMut { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_ref(); if _sync { BorshSerialize::serialize(bytes, writer) } else { - BorshSerializeAsync::serialize(bytes, writer).await + BorshSerializeAsync::serialize(bytes, writer) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] #[cfg(feature = "bson")] impl BorshSerialize for bson::oid::ObjectId { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { - let bytes = self.bytes(); + fn as_bytes(r#ref: &bson::oid::ObjectId) -> &[u8; 12] { + // SAFETY: `ObjectId` is a `12` byte array. + unsafe { &*(r#ref as *const bson::oid::ObjectId as *const [u8; 12]) } + } + + let bytes = as_bytes(self); if _sync { - BorshSerialize::serialize(&bytes, writer) + writer.write_all(bytes) } else { - BorshSerializeAsync::serialize(&bytes, writer).await + writer.write_all(bytes) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + Sync, + T: BorshSerializeAsync, )] impl BorshSerialize for VecDeque where T: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -616,25 +656,26 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + Sync, + T: BorshSerializeAsync, )] impl BorshSerialize for LinkedList where T: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; - let bytes =(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(); + let len = u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?; if _sync { - writer.write_all(&bytes) + BorshSerialize::serialize(&len, writer) } else { - writer.write_all(&bytes).await + BorshSerializeAsync::serialize(&len, writer).await }?; for item in self { if _sync { @@ -649,16 +690,20 @@ where /// Module is available if borsh is built with `features = ["std"]` or `features = ["hashbrown"]`. /// -/// Module defines [BorshSerialize] implementation for -/// [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet). +/// Module defines [`BorshSerialize`] +#[cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] +/// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { + #[cfg(feature = "async")] + use core::future::Future; use core::{convert::TryFrom, hash::BuildHasher}; use async_generic::async_generic; - #[cfg(feature = "async")] - use async_trait::async_trait; + use super::BorshSerialize; + #[cfg(feature = "async")] + use super::{AsyncWrite, BorshSerializeAsync}; use crate::{ __private::maybestd::{ collections::{HashMap, HashSet}, @@ -667,17 +712,13 @@ pub mod hashes { error::check_zst, io::{ErrorKind, Result, Write}, }; - use super::BorshSerialize; - #[cfg(feature = "async")] - use super::{AsyncWrite, BorshSerializeAsync}; #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - K: BorshSerializeAsync + Ord + Sync, - V: BorshSerializeAsync + Sync, + K: BorshSerializeAsync + Ord, + V: BorshSerializeAsync, H: BuildHasher + Sync, )] impl BorshSerialize for HashMap @@ -687,7 +728,9 @@ pub mod hashes { H: BuildHasher, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -712,10 +755,9 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + Ord + Sync, + T: BorshSerializeAsync + Ord, H: BuildHasher + Sync, )] impl BorshSerialize for HashSet @@ -724,7 +766,9 @@ pub mod hashes { H: BuildHasher, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -750,11 +794,10 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - K: BorshSerializeAsync + Sync, - V: BorshSerializeAsync + Sync, + K: BorshSerializeAsync, + V: BorshSerializeAsync, )] impl BorshSerialize for BTreeMap where @@ -762,7 +805,9 @@ where V: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; // NOTE: BTreeMap iterates over the entries that are sorted by key, so the serialization @@ -789,7 +834,6 @@ where #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where T: BorshSerializeAsync + Sync, @@ -799,7 +843,9 @@ where T: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; // NOTE: BTreeSet iterates over the items that are sorted, so the serialization result will @@ -824,27 +870,32 @@ where #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for std::net::SocketAddr { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { match self { - std::net::SocketAddr::V4(addr) => if _sync { - BorshSerialize::serialize(&0u8, writer)?; - BorshSerialize::serialize(addr, writer) - } else { - BorshSerializeAsync::serialize(&0u8, writer).await?; - BorshSerializeAsync::serialize(addr, writer).await + std::net::SocketAddr::V4(addr) => { + if _sync { + BorshSerialize::serialize(&0u8, writer)?; + BorshSerialize::serialize(addr, writer) + } else { + BorshSerializeAsync::serialize(&0u8, writer).await?; + BorshSerializeAsync::serialize(addr, writer).await + } } - std::net::SocketAddr::V6(addr) => if _sync { - BorshSerialize::serialize(&1u8, writer)?; - BorshSerialize::serialize(addr, writer) - } else { - BorshSerializeAsync::serialize(&1u8, writer).await?; - BorshSerializeAsync::serialize(addr, writer).await + std::net::SocketAddr::V6(addr) => { + if _sync { + BorshSerialize::serialize(&1u8, writer)?; + BorshSerialize::serialize(addr, writer) + } else { + BorshSerializeAsync::serialize(&1u8, writer).await?; + BorshSerializeAsync::serialize(addr, writer).await + } } } } @@ -853,12 +904,13 @@ impl BorshSerialize for std::net::SocketAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for std::net::SocketAddrV4 { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { BorshSerialize::serialize(self.ip(), writer)?; @@ -873,12 +925,13 @@ impl BorshSerialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for std::net::SocketAddrV6 { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { BorshSerialize::serialize(self.ip(), writer)?; @@ -893,17 +946,24 @@ impl BorshSerialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for std::net::Ipv4Addr { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { + fn as_bytes(ip: &std::net::Ipv4Addr) -> &[u8; 4] { + // SAFETY: `Ipv4Addr` is a `4` byte array. + unsafe { &*(ip as *const std::net::Ipv4Addr as *const [u8; 4]) } + } + + let bytes = as_bytes(self); if _sync { - writer.write_all(&self.octets()) + writer.write_all(bytes) } else { - writer.write_all(&self.octets()).await + writer.write_all(bytes) } } } @@ -911,17 +971,24 @@ impl BorshSerialize for std::net::Ipv4Addr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for std::net::Ipv6Addr { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { + fn as_bytes(ip: &std::net::Ipv6Addr) -> &[u8; 16] { + // SAFETY: `Ipv4Addr` is a `16` byte array. + unsafe { &*(ip as *const std::net::Ipv6Addr as *const [u8; 16]) } + } + + let bytes = as_bytes(self); if _sync { - writer.write_all(&self.octets()) + writer.write_all(bytes) } else { - writer.write_all(&self.octets()).await + writer.write_all(bytes) } } } @@ -929,27 +996,32 @@ impl BorshSerialize for std::net::Ipv6Addr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for std::net::IpAddr { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { match self { - std::net::IpAddr::V4(ipv4) => if _sync { - writer.write_all(&0u8.to_le_bytes())?; - BorshSerialize::serialize(ipv4, writer) - } else { - writer.write_all(&0u8.to_le_bytes()).await?; - BorshSerializeAsync::serialize(ipv4, writer).await + std::net::IpAddr::V4(ipv4) => { + if _sync { + writer.write_all(&0u8.to_le_bytes())?; + BorshSerialize::serialize(ipv4, writer) + } else { + writer.write_all(&0u8.to_le_bytes()).await?; + BorshSerializeAsync::serialize(ipv4, writer).await + } } - std::net::IpAddr::V6(ipv6) => if _sync { - writer.write_all(&1u8.to_le_bytes())?; - BorshSerialize::serialize(ipv6, writer) - } else { - writer.write_all(&1u8.to_le_bytes()).await?; - BorshSerializeAsync::serialize(ipv6, writer).await + std::net::IpAddr::V6(ipv6) => { + if _sync { + writer.write_all(&1u8.to_le_bytes())?; + BorshSerialize::serialize(ipv6, writer) + } else { + writer.write_all(&1u8.to_le_bytes()).await?; + BorshSerializeAsync::serialize(ipv6, writer).await + } } } } @@ -957,37 +1029,39 @@ impl BorshSerialize for std::net::IpAddr { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + ?Sized + Sync, + T: BorshSerializeAsync + ?Sized, )] impl BorshSerialize for Box { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { let r#ref = self.as_ref(); if _sync { BorshSerialize::serialize(r#ref, writer) } else { - BorshSerializeAsync::serialize(r#ref, writer).await + BorshSerializeAsync::serialize(r#ref, writer) } } } #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait where - T: BorshSerializeAsync + Sync, + T: BorshSerializeAsync, )] impl BorshSerialize for [T; N] where T: BorshSerialize, { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if N == 0 { Ok(()) @@ -998,7 +1072,7 @@ where writer.write_all(u8_slice).await } } else { - for el in self.iter() { + for el in self { if _sync { BorshSerialize::serialize(el, writer) } else { @@ -1014,13 +1088,14 @@ macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait )] impl BorshSerialize for $name { #[inline] - #[async_generic(async_signature(&self, _writer: &mut W) -> Result<()>)] - fn serialize(&self, _writer: &mut W) -> Result<()> { + #[async_generic( + async_signature[ready]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] + fn serialize(&self, _: &mut W) -> Result<()> { Ok(()) } } @@ -1029,17 +1104,18 @@ macro_rules! impl_tuple { ($($idx:tt $name:ident)+) => { #[async_generic( #[cfg(feature = "async")] - #[async_trait] async_trait<$($name),+> where - $($name: BorshSerializeAsync + Sync + Send,)+ + $($name: BorshSerializeAsync,)+ )] impl<$($name),+> BorshSerialize for ($($name,)+) where $($name: BorshSerialize,)+ { #[inline] - #[async_generic(async_signature(&self, writer: &mut W) -> Result<()>)] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { $(BorshSerialize::serialize(&self.$idx, writer)?;)+ From ecdbd3c4abb1e37f9668021b924eb153a529e169 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 00:55:59 +0200 Subject: [PATCH 09/69] inline inner `as_bytes` fns; use `write_u32` for `len` --- borsh/src/ser/mod.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index b0e82a574..76049fdc6 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -474,14 +474,12 @@ where async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { - let len = u32::try_from(self.len()) - .map_err(|_| ErrorKind::InvalidData)? - .to_le_bytes(); + let len = u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?; if _sync { - writer.write_all(&len)?; + writer.write_all(&len.to_le_bytes())?; serialize_slice(self, writer) } else { - writer.write_all(&len).await?; + writer.write_u32(len).await?; serialize_slice_async(self, writer).await } } @@ -609,6 +607,7 @@ impl BorshSerialize for bson::oid::ObjectId { async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { + #[inline(always)] fn as_bytes(r#ref: &bson::oid::ObjectId) -> &[u8; 12] { // SAFETY: `ObjectId` is a `12` byte array. unsafe { &*(r#ref as *const bson::oid::ObjectId as *const [u8; 12]) } @@ -640,14 +639,14 @@ where fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; - let bytes = (u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?).to_le_bytes(); + let len = u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?; let slices = self.as_slices(); if _sync { - writer.write_all(&bytes)?; + writer.write_all(&len.to_le_bytes())?; serialize_slice(slices.0, writer)?; serialize_slice(slices.1, writer) } else { - writer.write_all(&bytes).await?; + writer.write_u32(len).await?; serialize_slice_async(slices.0, writer).await?; serialize_slice_async(slices.1, writer).await } @@ -675,7 +674,7 @@ where if _sync { BorshSerialize::serialize(&len, writer) } else { - BorshSerializeAsync::serialize(&len, writer).await + writer.write_u32(len).await }?; for item in self { if _sync { @@ -740,7 +739,7 @@ pub mod hashes { if _sync { BorshSerialize::serialize(&len, writer) } else { - BorshSerializeAsync::serialize(&len, writer).await + writer.write_u32(len).await }?; for kv in vec { if _sync { @@ -778,7 +777,7 @@ pub mod hashes { if _sync { BorshSerialize::serialize(&len, writer) } else { - BorshSerializeAsync::serialize(&len, writer).await + writer.write_u32(len).await }?; for item in vec { if _sync { @@ -817,7 +816,7 @@ where if _sync { BorshSerialize::serialize(&len, writer) } else { - BorshSerializeAsync::serialize(&len, writer).await + writer.write_u32(len).await }?; for (key, value) in self { if _sync { @@ -854,7 +853,7 @@ where if _sync { BorshSerialize::serialize(&len, writer) } else { - BorshSerializeAsync::serialize(&len, writer).await + writer.write_u32(len).await }?; for item in self { if _sync { @@ -954,6 +953,7 @@ impl BorshSerialize for std::net::Ipv4Addr { async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { + #[inline(always)] fn as_bytes(ip: &std::net::Ipv4Addr) -> &[u8; 4] { // SAFETY: `Ipv4Addr` is a `4` byte array. unsafe { &*(ip as *const std::net::Ipv4Addr as *const [u8; 4]) } @@ -979,6 +979,7 @@ impl BorshSerialize for std::net::Ipv6Addr { async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { + #[inline(always)] fn as_bytes(ip: &std::net::Ipv6Addr) -> &[u8; 16] { // SAFETY: `Ipv4Addr` is a `16` byte array. unsafe { &*(ip as *const std::net::Ipv6Addr as *const [u8; 16]) } From 037bc31f8acbf2ba1fb3eca7220aea5750912dd2 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 00:58:28 +0200 Subject: [PATCH 10/69] Update workflow Rust version --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 087983950..428f7c1d1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -20,7 +20,7 @@ jobs: tests: strategy: matrix: - rust_version: [1.67, stable] + rust_version: [1.75.0, stable] runs-on: ubuntu-20.04 steps: From e5216c51adb3290d7e2b0380e175d59d9668238e Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 01:09:06 +0200 Subject: [PATCH 11/69] Formatting & remove redundant imports --- borsh/examples/serde_json_value.rs | 5 +- borsh/src/async_io.rs | 25 ++++++-- borsh/src/de/mod.rs | 26 ++------- borsh/src/error.rs | 3 +- borsh/src/generate_schema_schema.rs | 4 +- borsh/src/lib.rs | 24 ++++---- borsh/src/nostd_io.rs | 3 +- borsh/src/schema.rs | 58 +++++++++---------- borsh/src/schema/container_ext.rs | 4 +- borsh/src/schema/container_ext/max_size.rs | 9 +-- borsh/src/schema/container_ext/validate.rs | 3 +- borsh/src/schema_helpers.rs | 12 ++-- borsh/src/ser/helpers.rs | 10 ++-- borsh/tests/common_macro.rs | 10 ++-- .../tests/custom_reader/test_custom_reader.rs | 4 +- .../test_ascii_strings.rs | 1 + .../deserialization_errors/test_initial.rs | 9 ++- .../test_zero_sized_types_forbidden.rs | 18 +++--- 18 files changed, 112 insertions(+), 116 deletions(-) diff --git a/borsh/examples/serde_json_value.rs b/borsh/examples/serde_json_value.rs index 21cadf758..ad60cae16 100644 --- a/borsh/examples/serde_json_value.rs +++ b/borsh/examples/serde_json_value.rs @@ -3,14 +3,13 @@ use std::collections::HashMap; use borsh::{BorshDeserialize, BorshSerialize}; mod serde_json_value { - pub use de::deserialize_value; - pub use ser::serialize_value; mod ser { + use core::convert::TryFrom; + use borsh::{ io::{ErrorKind, Result, Write}, BorshSerialize, }; - use core::convert::TryFrom; /// this is mutually recursive with `serialize_array` and `serialize_map` pub fn serialize_value(value: &serde_json::Value, writer: &mut W) -> Result<()> { diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index b8e3a2489..d01a5611a 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -5,9 +5,13 @@ use std::io::Result; // #[async_trait] pub trait AsyncRead: Unpin + Send { - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a; + fn read<'a>(&'a mut self, buf: &'a mut [u8]) + -> impl Future> + Send + 'a; - fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a; + fn read_exact<'a>( + &'a mut self, + buf: &'a mut [u8], + ) -> impl Future> + Send + 'a; fn read_u8<'a>(&'a mut self) -> impl Future> + Send + 'a { async { @@ -115,7 +119,10 @@ impl AsyncRead for R { } #[inline] - fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { + fn read_exact<'a>( + &'a mut self, + buf: &'a mut [u8], + ) -> impl Future> + Send + 'a { async { tokio::io::AsyncReadExt::read_exact(self, buf) .await @@ -188,12 +195,18 @@ impl AsyncRead for R { // #[async_trait] impl AsyncRead for R { #[inline] - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { + fn read<'a>( + &'a mut self, + buf: &'a mut [u8], + ) -> impl Future> + Send + 'a { async_std::io::ReadExt::read(self, buf) } #[inline] - fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { + fn read_exact<'a>( + &'a mut self, + buf: &'a mut [u8], + ) -> impl Future> + Send + 'a { async_std::io::ReadExt::read_exact(self, buf) } } @@ -201,7 +214,7 @@ impl AsyncRead for R { // #[async_trait] pub trait AsyncWrite: Unpin + Send { fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a; - + fn write_u8<'a>(&'a mut self, n: u8) -> impl Future> + Send + 'a { async move { let bytes = n.to_le_bytes(); diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 01a6a4a1d..72a036a7f 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -189,7 +189,9 @@ impl BorshDeserialize for u8 { fn deserialize_reader(reader: &mut R) -> Result { if _sync { let mut buf = [0u8; 1]; - reader.read_exact(&mut buf).map_err(unexpected_eof_to_unexpected_length_of_input)?; + reader + .read_exact(&mut buf) + .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(buf[0]) } else { reader.read_u8() @@ -365,7 +367,7 @@ macro_rules! impl_for_float { reader .read_exact(&mut buf) .map_err(unexpected_eof_to_unexpected_length_of_input)?; - $type::from_bits($int_type::from_le_bytes(buf.try_into().unwrap())) + $type::from_bits($int_type::from_le_bytes(buf.try_into().unwrap())) } else { reader.$method().await? }; @@ -1276,9 +1278,7 @@ where // TODO: replace with `core::array::try_from_fn` when stabilized to avoid manually // dropping uninitialized values through the guard drop. for elem in self.buffer.iter_mut() { - elem.write( - T::deserialize_reader(self.reader).await?, - ); + elem.write(T::deserialize_reader(self.reader).await?); self.init_count += 1; } Ok(()) @@ -1482,27 +1482,13 @@ pub mod rc { /// Deserializing a data structure containing `Rc` will not attempt to /// deduplicate `Rc` references to the same data. Every deserialized `Rc` /// will end up with a strong count of 1. - // #[async_generic( - // #[cfg(feature = "async")] - // async_trait - // where - // Box: BorshDeserializeAsync, - // )] impl BorshDeserialize for Rc where Box: BorshDeserialize, { #[inline] - // #[async_generic( - // async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - // )] fn deserialize_reader(reader: &mut R) -> Result { - Ok(//if _sync { - >::deserialize_reader(reader) - // } else { - // >::deserialize_reader(reader).await - /*}*/? - .into()) + Ok(>::deserialize_reader(reader)?.into()) } } diff --git a/borsh/src/error.rs b/borsh/src/error.rs index 9afc88c09..623c70564 100644 --- a/borsh/src/error.rs +++ b/borsh/src/error.rs @@ -1,5 +1,6 @@ -use crate::io::{Error, ErrorKind, Result}; use core::mem::size_of; + +use crate::io::{Error, ErrorKind, Result}; pub const ERROR_ZST_FORBIDDEN: &str = "Collections of zero-sized types are not allowed due to deny-of-service concerns on deserialization."; pub(crate) fn check_zst() -> Result<()> { diff --git a/borsh/src/generate_schema_schema.rs b/borsh/src/generate_schema_schema.rs index 647816318..f2baaa98c 100644 --- a/borsh/src/generate_schema_schema.rs +++ b/borsh/src/generate_schema_schema.rs @@ -1,9 +1,9 @@ //! Generate `BorshSchemaCointainer` for `BorshSchemaContainer` and save it into a file. #![cfg_attr(not(feature = "std"), no_std)] +use std::{fs::File, io::Write}; + use borsh::schema_container_of; -use std::fs::File; -use std::io::Write; fn main() { let container = schema_container_of::(); diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index cf69044ed..dcda22db5 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -4,14 +4,12 @@ #[cfg(not(feature = "std"))] extern crate alloc; -#[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_deserialize.md")] #[cfg(feature = "derive")] pub use borsh_derive::BorshDeserialize; - +#[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; @@ -26,16 +24,17 @@ pub mod schema; pub(crate) mod schema_helpers; pub mod ser; -pub use de::BorshDeserialize; -pub use de::{from_reader, from_slice}; +pub use de::{from_reader, from_slice, BorshDeserialize}; #[cfg(feature = "unstable__schema")] pub use schema::BorshSchema; #[cfg(feature = "unstable__schema")] pub use schema_helpers::{ max_serialized_size, schema_container_of, try_from_slice_with_schema, try_to_vec_with_schema, }; -pub use ser::helpers::{object_length, to_vec, to_writer}; -pub use ser::BorshSerialize; +pub use ser::{ + helpers::{object_length, to_vec, to_writer}, + BorshSerialize, +}; pub mod error; #[cfg(all(feature = "std", feature = "hashbrown"))] @@ -46,10 +45,10 @@ compile_error!("Cannot enable both `async-tokio` and `async-std` features at the #[cfg(feature = "std")] use std::io as io_impl; -#[cfg(not(feature = "std"))] -mod nostd_io; #[cfg(feature = "async")] pub mod async_io; +#[cfg(not(feature = "std"))] +mod nostd_io; #[cfg(not(feature = "std"))] use nostd_io as io_impl; @@ -72,19 +71,18 @@ pub mod __private { #[cfg(feature = "std")] pub mod maybestd { pub use std::{borrow, boxed, collections, format, string, vec}; - #[cfg(feature = "rc")] pub use std::{rc, sync}; } #[cfg(not(feature = "std"))] pub mod maybestd { pub use alloc::{borrow, boxed, format, string, vec}; - #[cfg(feature = "rc")] pub use alloc::{rc, sync}; pub mod collections { pub use alloc::collections::{btree_map, BTreeMap, BTreeSet, LinkedList, VecDeque}; + #[cfg(feature = "hashbrown")] pub use hashbrown::*; } diff --git a/borsh/src/nostd_io.rs b/borsh/src/nostd_io.rs index 52061b817..b59d385de 100644 --- a/borsh/src/nostd_io.rs +++ b/borsh/src/nostd_io.rs @@ -1,8 +1,9 @@ //! Taken from https://github.com/bbqsrc/bare-io (with adjustments) -use crate::__private::maybestd::string::String; use core::{convert::From, fmt, result}; +use crate::__private::maybestd::string::String; + /// A specialized [`Result`] type for I/O operations. /// /// This type is broadly used across [`std::io`] for any operation which may diff --git a/borsh/src/schema.rs b/borsh/src/schema.rs index e9dad6350..7d07546b5 100644 --- a/borsh/src/schema.rs +++ b/borsh/src/schema.rs @@ -6,27 +6,30 @@ //! on Rust side. //! //! The important components are: `BorshSchema` trait, `Definition` and `Declaration` types, and `BorshSchemaContainer` struct. -//! * `BorshSchema` trait allows any type that implements it to be self-descriptive, i.e. generate it's own schema; +//! * `BorshSchema` trait allows any type that implements it to be self-descriptive, i.e. generate its own schema; //! * `Declaration` is used to describe the type identifier, e.g. `HashMap`; //! * `Definition` is used to describe the structure of the type; //! * `BorshSchemaContainer` is used to store all declarations and definitions that are needed to work with a single type. #![allow(dead_code)] // Unclear why rust check complains on fields of `Definition` variants. -use crate as borsh; // For `#[derive(BorshSerialize, BorshDeserialize, BorshSchema)]`. -use crate::__private::maybestd::{ - borrow, - boxed::Box, - collections::{btree_map::Entry, BTreeMap, BTreeSet, LinkedList, VecDeque}, - format, - string::{String, ToString}, - vec, - vec::Vec, + +use core::{borrow::Borrow, cmp::Ord, marker::PhantomData}; + +use crate as borsh; +// For `#[derive(BorshSerialize, BorshDeserialize, BorshSchema)]`. +use crate::{ + __private::maybestd::{ + borrow, + boxed::Box, + collections::{btree_map::Entry, BTreeMap, BTreeSet, LinkedList, VecDeque}, + format, + string::{String, ToString}, + vec, + vec::Vec, + }, + io::{Read, Result as IOResult, Write}, + BorshDeserialize, BorshSchema as BorshSchemaMacro, BorshSerialize, }; -use crate::io::{Read, Result as IOResult, Write}; -use crate::{BorshDeserialize, BorshSchema as BorshSchemaMacro, BorshSerialize}; -use core::borrow::Borrow; -use core::cmp::Ord; -use core::marker::PhantomData; mod container_ext; @@ -350,11 +353,11 @@ pub mod rc { //! //! Module defines [BorshSchema] implementation for //! [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). - use crate::BorshSchema; - use super::{Declaration, Definition}; - use crate::__private::maybestd::collections::BTreeMap; - use crate::__private::maybestd::{rc::Rc, sync::Arc}; + use crate::{ + BorshSchema, + __private::maybestd::{collections::BTreeMap, rc::Rc, sync::Arc}, + }; impl BorshSchema for Rc where @@ -487,10 +490,8 @@ pub mod ascii { //! //! Module defines [BorshSchema] implementation for //! some types from [ascii](::ascii) crate. - use crate::BorshSchema; - use super::{add_definition, Declaration, Definition}; - use crate::__private::maybestd::collections::BTreeMap; + use crate::{BorshSchema, __private::maybestd::collections::BTreeMap}; impl BorshSchema for ascii::AsciiString { #[inline] @@ -575,7 +576,6 @@ where T: BorshSchema, { fn add_definitions_recursively(definitions: &mut BTreeMap) { - use core::convert::TryFrom; let length = u64::try_from(N).unwrap(); let definition = Definition::Sequence { length_width: Definition::ARRAY_LENGTH_WIDTH, @@ -687,15 +687,15 @@ where /// [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { - use crate::BorshSchema; - - use super::{add_definition, Declaration, Definition}; - use crate::__private::maybestd::collections::BTreeMap; - - use crate::__private::maybestd::collections::{HashMap, HashSet}; #[cfg(not(feature = "std"))] use alloc::format; + use super::{add_definition, Declaration, Definition}; + use crate::{ + BorshSchema, + __private::maybestd::collections::{BTreeMap, HashMap, HashSet}, + }; + // S is not serialized, so we ignore it in schema too // forcing S to be BorshSchema forces to define Definition // which must be empty, but if not - it will fail diff --git a/borsh/src/schema/container_ext.rs b/borsh/src/schema/container_ext.rs index ba1f95982..e348a9e09 100644 --- a/borsh/src/schema/container_ext.rs +++ b/borsh/src/schema/container_ext.rs @@ -1,8 +1,8 @@ -use super::{BorshSchemaContainer, Declaration, Definition, Fields}; - pub use max_size::Error as SchemaMaxSerializedSizeError; use max_size::{is_zero_size, ZeroSizeError}; pub use validate::Error as SchemaContainerValidateError; +use super::{BorshSchemaContainer, Declaration, Definition, Fields}; + mod max_size; mod validate; diff --git a/borsh/src/schema/container_ext/max_size.rs b/borsh/src/schema/container_ext/max_size.rs index 193f3be1e..3be5d3936 100644 --- a/borsh/src/schema/container_ext/max_size.rs +++ b/borsh/src/schema/container_ext/max_size.rs @@ -1,8 +1,8 @@ +use core::num::NonZeroUsize; + use super::{BorshSchemaContainer, Declaration, Definition, Fields}; use crate::__private::maybestd::{string::ToString, vec::Vec}; -use core::num::NonZeroUsize; - /// NonZeroUsize of value one. // TODO: Replace usage by NonZeroUsize::MIN once MSRV is 1.70+. const ONE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(1) }; @@ -13,7 +13,7 @@ impl BorshSchemaContainer { /// Even when if returned upper bound is correct, the theoretical value may be /// *much* larger than any practical length. For example, maximum encoded /// length of `String` is 4 GiB while in practice one may encounter strings of - /// at most dozen of characters. + /// at most a dozen of characters. /// /// # Example /// @@ -66,8 +66,6 @@ fn max_serialized_size_impl<'a>( schema: &'a BorshSchemaContainer, stack: &mut Vec<&'a str>, ) -> Result { - use core::convert::TryFrom; - /// Maximum number of elements in a vector or length of a string which can /// be serialised. const MAX_LEN: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(u32::MAX as usize) }; @@ -263,7 +261,6 @@ fn is_zero_size_impl<'a>( #[cfg(test)] mod tests { use super::*; - // this is not integration test module, so can use __private for ease of imports; // it cannot be made integration, as it tests `is_zero_size` function, chosen to be non-pub use crate::__private::maybestd::{boxed::Box, string::ToString}; diff --git a/borsh/src/schema/container_ext/validate.rs b/borsh/src/schema/container_ext/validate.rs index 6bd2738fb..e9798e75c 100644 --- a/borsh/src/schema/container_ext/validate.rs +++ b/borsh/src/schema/container_ext/validate.rs @@ -1,5 +1,4 @@ -use super::{is_zero_size, ZeroSizeError}; -use super::{BorshSchemaContainer, Declaration, Definition, Fields}; +use super::{is_zero_size, BorshSchemaContainer, Declaration, Definition, Fields, ZeroSizeError}; use crate::__private::maybestd::{string::ToString, vec::Vec}; impl BorshSchemaContainer { diff --git a/borsh/src/schema_helpers.rs b/borsh/src/schema_helpers.rs index 422c36138..7cacabca4 100644 --- a/borsh/src/schema_helpers.rs +++ b/borsh/src/schema_helpers.rs @@ -1,8 +1,10 @@ -use crate::__private::maybestd::vec::Vec; -use crate::from_slice; -use crate::io::{Error, ErrorKind, Result}; -use crate::schema::{BorshSchemaContainer, SchemaMaxSerializedSizeError}; -use crate::{BorshDeserialize, BorshSchema, BorshSerialize}; +use crate::{ + __private::maybestd::vec::Vec, + from_slice, + io::{Error, ErrorKind, Result}, + schema::{BorshSchemaContainer, SchemaMaxSerializedSizeError}, + BorshDeserialize, BorshSchema, BorshSerialize, +}; /// Deserialize this instance from a slice of bytes, but assume that at the beginning we have /// bytes describing the schema of the type. We deserialize this schema and verify that it is diff --git a/borsh/src/ser/helpers.rs b/borsh/src/ser/helpers.rs index da4da27da..699f08843 100644 --- a/borsh/src/ser/helpers.rs +++ b/borsh/src/ser/helpers.rs @@ -1,6 +1,8 @@ -use crate::BorshSerialize; -use crate::__private::maybestd::vec::Vec; -use crate::io::{ErrorKind, Result, Write}; +use crate::{ + BorshSerialize, + __private::maybestd::vec::Vec, + io::{ErrorKind, Result, Write}, +}; pub(super) const DEFAULT_SERIALIZER_CAPACITY: usize = 1024; @@ -47,7 +49,7 @@ where /// struct A { /// tag: String, /// value: u64, -/// }; +/// } /// /// # #[cfg(feature = "derive")] /// let a = A { tag: "hello".to_owned(), value: 42 }; diff --git a/borsh/tests/common_macro.rs b/borsh/tests/common_macro.rs index bc5503ffb..dd82b0bf8 100644 --- a/borsh/tests/common_macro.rs +++ b/borsh/tests/common_macro.rs @@ -137,9 +137,11 @@ pub mod schema_imports { vec::Vec, }; - pub use borsh::schema::{ - add_definition, BorshSchemaContainer, Declaration, Definition, Fields, - SchemaContainerValidateError, SchemaMaxSerializedSizeError, + pub use borsh::{ + schema::{ + add_definition, BorshSchemaContainer, Declaration, Definition, Fields, + SchemaContainerValidateError, SchemaMaxSerializedSizeError, + }, + schema_container_of, BorshSchema, }; - pub use borsh::{schema_container_of, BorshSchema}; } diff --git a/borsh/tests/custom_reader/test_custom_reader.rs b/borsh/tests/custom_reader/test_custom_reader.rs index e0c6dc7de..aadd3f934 100644 --- a/borsh/tests/custom_reader/test_custom_reader.rs +++ b/borsh/tests/custom_reader/test_custom_reader.rs @@ -1,10 +1,10 @@ -use borsh::{from_reader, to_vec, BorshDeserialize, BorshSerialize}; - use alloc::{ string::{String, ToString}, vec::Vec, }; +use borsh::{from_reader, to_vec, BorshDeserialize, BorshSerialize}; + const ERROR_NOT_ALL_BYTES_READ: &str = "Not all bytes read"; const ERROR_UNEXPECTED_LENGTH_OF_INPUT: &str = "Unexpected length of input"; diff --git a/borsh/tests/deserialization_errors/test_ascii_strings.rs b/borsh/tests/deserialization_errors/test_ascii_strings.rs index ffcf90d8e..8f8ef786c 100644 --- a/borsh/tests/deserialization_errors/test_ascii_strings.rs +++ b/borsh/tests/deserialization_errors/test_ascii_strings.rs @@ -1,4 +1,5 @@ use alloc::string::ToString; + use borsh::from_slice; #[test] diff --git a/borsh/tests/deserialization_errors/test_initial.rs b/borsh/tests/deserialization_errors/test_initial.rs index 0fef5c5eb..33a33a086 100644 --- a/borsh/tests/deserialization_errors/test_initial.rs +++ b/borsh/tests/deserialization_errors/test_initial.rs @@ -1,8 +1,3 @@ -use borsh::from_slice; - -#[cfg(feature = "derive")] -use borsh::BorshDeserialize; - use alloc::{ format, string::{String, ToString}, @@ -10,6 +5,10 @@ use alloc::{ vec::Vec, }; +use borsh::from_slice; +#[cfg(feature = "derive")] +use borsh::BorshDeserialize; + #[cfg(feature = "derive")] #[derive(BorshDeserialize, Debug)] #[borsh(use_discriminant = true)] diff --git a/borsh/tests/zero_sized_types/test_zero_sized_types_forbidden.rs b/borsh/tests/zero_sized_types/test_zero_sized_types_forbidden.rs index c48b9cf77..a88528f96 100644 --- a/borsh/tests/zero_sized_types/test_zero_sized_types_forbidden.rs +++ b/borsh/tests/zero_sized_types/test_zero_sized_types_forbidden.rs @@ -1,19 +1,15 @@ -use alloc::{string::ToString, vec, vec::Vec}; - +use alloc::{ + collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, + string::ToString, + vec, + vec::Vec, +}; #[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; +use borsh::{error::ERROR_ZST_FORBIDDEN, from_slice, to_vec, BorshDeserialize, BorshSerialize}; #[cfg(feature = "hashbrown")] use hashbrown::{HashMap, HashSet}; - -use alloc::collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}; - -use borsh::from_slice; -use borsh::to_vec; -use borsh::BorshDeserialize; -use borsh::BorshSerialize; - -use borsh::error::ERROR_ZST_FORBIDDEN; #[derive(BorshDeserialize, BorshSerialize, PartialEq, Debug, Eq, PartialOrd, Ord, Hash)] struct A(); From bb3d210e560d279acf78fa3e504fdcac2fcb0469 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 01:12:25 +0200 Subject: [PATCH 12/69] Rollback remove unused imports. Add `#[allow(unused_imports)]` --- borsh/examples/serde_json_value.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/borsh/examples/serde_json_value.rs b/borsh/examples/serde_json_value.rs index ad60cae16..dbbd599d8 100644 --- a/borsh/examples/serde_json_value.rs +++ b/borsh/examples/serde_json_value.rs @@ -3,6 +3,11 @@ use std::collections::HashMap; use borsh::{BorshDeserialize, BorshSerialize}; mod serde_json_value { + #[allow(unused_imports)] // used in attribute + pub use de::deserialize_value; + #[allow(unused_imports)] // used in attribute + pub use ser::serialize_value; + mod ser { use core::convert::TryFrom; From 7dacd4c7ee58d69e675ad47fc4d5169c5c97ce22 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 15:16:40 +0200 Subject: [PATCH 13/69] Add support for mutex/rwlock (de-)serialization (including async counterparts); Code cleanup --- Cargo.toml | 1 + borsh/Cargo.toml | 5 + borsh/src/async_io.rs | 118 +++++----- borsh/src/de/mod.rs | 494 +++++++++++++++++++++++------------------- borsh/src/ser/mod.rs | 230 ++++++++++++++------ rustfmt.toml | 2 +- 6 files changed, 500 insertions(+), 350 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f098baa67..9977a334f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = ["borsh", "borsh-derive", "fuzz/fuzz-run", "benchmarks"] [workspace.package] diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 41b815a0e..725a80ffa 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -44,6 +44,7 @@ bson = { version = "2", optional = true } async-generic = { git = "https://github.com/DanikVitek/async-generic.git" } tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } async-std = { version = "1", default-features = false, features = ["std"], optional = true } +lock_api = { version = "0.4", optional = true } [dev-dependencies] insta = "1.29.0" @@ -58,7 +59,11 @@ default = ["std"] derive = ["borsh-derive"] async = [] tokio = ["async", "dep:tokio"] +tokio-sync = ["tokio", "tokio/sync"] # (de-)serialization for tokio mutex/rwlock primitives async-std = ["async", "dep:async-std"] +async-std-sync = ["async-std", "async-std/async-lock"] # (de-)serialization for async-std mutex/rwlock primitives +lock_api = [] # (de-)serialization for lock_api mutex/rwlock primitives +parking_lot = ["dep:lock_api"] # aslias for lock_api feature unstable__schema = ["derive", "borsh-derive/schema"] std = [] # Opt into impls for Rc and Arc. Serializing and deserializing these types diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index d01a5611a..73ebbcf7e 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -1,9 +1,6 @@ use core::future::Future; use std::io::Result; -// use async_trait::async_trait; - -// #[async_trait] pub trait AsyncRead: Unpin + Send { fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a; @@ -13,7 +10,7 @@ pub trait AsyncRead: Unpin + Send { buf: &'a mut [u8], ) -> impl Future> + Send + 'a; - fn read_u8<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u8(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 1]; self.read_exact(&mut buf).await?; @@ -21,7 +18,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u16<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u16(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 2]; self.read_exact(&mut buf).await?; @@ -29,7 +26,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u32<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u32(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 4]; self.read_exact(&mut buf).await?; @@ -37,7 +34,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u64<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u64(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 8]; self.read_exact(&mut buf).await?; @@ -45,7 +42,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u128<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u128(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 16]; self.read_exact(&mut buf).await?; @@ -53,7 +50,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i8<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i8(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 1]; self.read_exact(&mut buf).await?; @@ -61,7 +58,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i16<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i16(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 2]; self.read_exact(&mut buf).await?; @@ -69,7 +66,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i32<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i32(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 4]; self.read_exact(&mut buf).await?; @@ -77,7 +74,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i64<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i64(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 8]; self.read_exact(&mut buf).await?; @@ -85,7 +82,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i128<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i128(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 16]; self.read_exact(&mut buf).await?; @@ -93,7 +90,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_f32<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_f32(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 4]; self.read_exact(&mut buf).await?; @@ -101,7 +98,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_f64<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_f64(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 8]; self.read_exact(&mut buf).await?; @@ -114,85 +111,79 @@ pub trait AsyncRead: Unpin + Send { // #[async_trait] impl AsyncRead for R { #[inline] - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + 'a { + fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read(self, buf) } #[inline] - fn read_exact<'a>( - &'a mut self, - buf: &'a mut [u8], - ) -> impl Future> + Send + 'a { - async { - tokio::io::AsyncReadExt::read_exact(self, buf) - .await - .map(|_| ()) - } + async fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> Result<()> { + tokio::io::AsyncReadExt::read_exact(self, buf) + .await + .map(|_| ()) } #[inline] - fn read_u8<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u8(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u8(self) } #[inline] - fn read_u16<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u16(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u16_le(self) } #[inline] - fn read_u32<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u32(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u32_le(self) } #[inline] - fn read_u64<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u64(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u64_le(self) } #[inline] - fn read_u128<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_u128(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u128_le(self) } #[inline] - fn read_i8<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i8(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i8(self) } #[inline] - fn read_i16<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i16(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i16_le(self) } #[inline] - fn read_i32<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i32(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i32_le(self) } #[inline] - fn read_i64<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i64(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i64_le(self) } #[inline] - fn read_i128<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_i128(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i128_le(self) } #[inline] - fn read_f32<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_f32(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_f32_le(self) } #[inline] - fn read_f64<'a>(&'a mut self) -> impl Future> + Send + 'a { + fn read_f64(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_f64_le(self) } } #[cfg(feature = "async-std")] -// #[async_trait] impl AsyncRead for R { #[inline] fn read<'a>( @@ -211,11 +202,10 @@ impl AsyncRead for R { } } -// #[async_trait] pub trait AsyncWrite: Unpin + Send { fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a; - fn write_u8<'a>(&'a mut self, n: u8) -> impl Future> + Send + 'a { + fn write_u8(&mut self, n: u8) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -223,7 +213,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u16<'a>(&'a mut self, n: u16) -> impl Future> + Send + 'a { + fn write_u16(&mut self, n: u16) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -231,7 +221,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u32<'a>(&'a mut self, n: u32) -> impl Future> + Send + 'a { + fn write_u32(&mut self, n: u32) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -239,7 +229,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u64<'a>(&'a mut self, n: u64) -> impl Future> + Send + 'a { + fn write_u64(&mut self, n: u64) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -247,7 +237,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u128<'a>(&'a mut self, n: u128) -> impl Future> + Send + 'a { + fn write_u128(&mut self, n: u128) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -255,7 +245,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i8<'a>(&'a mut self, n: i8) -> impl Future> + Send + 'a { + fn write_i8(&mut self, n: i8) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -263,7 +253,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i16<'a>(&'a mut self, n: i16) -> impl Future> + Send + 'a { + fn write_i16(&mut self, n: i16) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -271,7 +261,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i32<'a>(&'a mut self, n: i32) -> impl Future> + Send + 'a { + fn write_i32(&mut self, n: i32) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -279,7 +269,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i64<'a>(&'a mut self, n: i64) -> impl Future> + Send + 'a { + fn write_i64(&mut self, n: i64) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -287,7 +277,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i128<'a>(&'a mut self, n: i128) -> impl Future> + Send + 'a { + fn write_i128(&mut self, n: i128) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -295,7 +285,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_f32<'a>(&'a mut self, n: f32) -> impl Future> + Send + 'a { + fn write_f32(&mut self, n: f32) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -303,7 +293,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_f64<'a>(&'a mut self, n: f64) -> impl Future> + Send + 'a { + fn write_f64(&mut self, n: f64) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -313,7 +303,6 @@ pub trait AsyncWrite: Unpin + Send { } #[cfg(feature = "tokio")] -// #[async_trait] impl AsyncWrite for R { #[inline] fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { @@ -321,68 +310,67 @@ impl AsyncWrite for R { } #[inline] - fn write_u8<'a>(&'a mut self, n: u8) -> impl Future> + Send + 'a { + fn write_u8(&mut self, n: u8) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u8(self, n) } #[inline] - fn write_u16<'a>(&'a mut self, n: u16) -> impl Future> + Send + 'a { + fn write_u16(&mut self, n: u16) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u16_le(self, n) } #[inline] - fn write_u32<'a>(&'a mut self, n: u32) -> impl Future> + Send + 'a { + fn write_u32(&mut self, n: u32) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u32_le(self, n) } #[inline] - fn write_u64<'a>(&'a mut self, n: u64) -> impl Future> + Send + 'a { + fn write_u64(&mut self, n: u64) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u64_le(self, n) } #[inline] - fn write_u128<'a>(&'a mut self, n: u128) -> impl Future> + Send + 'a { + fn write_u128(&mut self, n: u128) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u128_le(self, n) } #[inline] - fn write_i8<'a>(&'a mut self, n: i8) -> impl Future> + Send + 'a { + fn write_i8(&mut self, n: i8) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i8(self, n) } #[inline] - fn write_i16<'a>(&'a mut self, n: i16) -> impl Future> + Send + 'a { + fn write_i16(&mut self, n: i16) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i16_le(self, n) } #[inline] - fn write_i32<'a>(&'a mut self, n: i32) -> impl Future> + Send + 'a { + fn write_i32(&mut self, n: i32) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i32_le(self, n) } #[inline] - fn write_i64<'a>(&'a mut self, n: i64) -> impl Future> + Send + 'a { + fn write_i64(&mut self, n: i64) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i64_le(self, n) } #[inline] - fn write_i128<'a>(&'a mut self, n: i128) -> impl Future> + Send + 'a { + fn write_i128(&mut self, n: i128) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i128_le(self, n) } #[inline] - fn write_f32<'a>(&'a mut self, n: f32) -> impl Future> + Send + 'a { + fn write_f32(&mut self, n: f32) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_f32_le(self, n) } #[inline] - fn write_f64<'a>(&'a mut self, n: f64) -> impl Future> + Send + 'a { + fn write_f64(&mut self, n: f64) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_f64_le(self, n) } } #[cfg(feature = "async-std")] -// #[async_trait] impl AsyncWrite for R { #[inline] fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 72a036a7f..40ef037d9 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -73,10 +73,11 @@ pub trait BorshDeserialize: Sized { } else { Self::deserialize_reader(reader).await }?; - let mut buf = [0u8; 1]; + let mut buf = [0u8; 1]; let res = reader.read_exact(&mut buf); - match if _sync { res } else { res.await } { + let res = if _sync { res } else { res.await }; + match res { Err(f) if f.kind() == ErrorKind::UnexpectedEof => Ok(result), _ => Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)), } @@ -201,7 +202,7 @@ impl BorshDeserialize for u8 { #[inline] #[doc(hidden)] #[async_generic( - async_signature[impl_fut](len: u32, reader: &mut R) -> impl Future>>> + Send + async_signature(len: u32, reader: &mut R) -> Result>> )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let len: usize = len.try_into().map_err(|_| ErrorKind::InvalidData)?; @@ -216,10 +217,11 @@ impl BorshDeserialize for u8 { vec.resize(vec.len().saturating_mul(2).min(len), 0) } // TODO(mina86): Convert this to read_buf once that stabilises. - match { + let res = { let res = reader.read(&mut vec.as_mut_slice()[pos..]); if _sync { res } else { res.await }? - } { + }; + match res { 0 => { return Err(Error::new( ErrorKind::InvalidData, @@ -237,7 +239,7 @@ impl BorshDeserialize for u8 { #[inline] #[doc(hidden)] #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future>> + Send + async_signature(reader: &mut R) -> Result> )] fn array_from_reader(reader: &mut R) -> Result> { let mut arr = [0u8; N]; @@ -293,9 +295,7 @@ macro_rules! impl_for_nonzero_integer { )] impl BorshDeserialize for $type { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { <$type>::new(if _sync { <$repr as BorshDeserialize>::deserialize_reader(reader) @@ -324,13 +324,11 @@ impl_for_nonzero_integer!(core::num::NonZeroUsize, usize); macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { #[async_generic( - #[cfg(feature = "async")] - async_trait - )] + #[cfg(feature = "async")] + async_trait + )] impl BorshDeserialize for $type { - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let i = if _sync { <$temp_type as BorshDeserialize>::deserialize_reader(reader) @@ -353,14 +351,12 @@ impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); macro_rules! impl_for_float { ($type: ident, $int_type: ident, $method: ident) => { #[async_generic( - #[cfg(feature = "async")] - async_trait - )] + #[cfg(feature = "async")] + async_trait + )] impl BorshDeserialize for $type { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let res = if _sync { let mut buf = [0u8; size_of::<$type>()]; @@ -392,9 +388,7 @@ impl_for_float!(f64, u64, read_f64); )] impl BorshDeserialize for bool { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let b = if _sync { ::deserialize_reader(reader) @@ -423,9 +417,7 @@ where T: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let flag = if _sync { ::deserialize_reader(reader) @@ -464,9 +456,7 @@ where E: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let flag = if _sync { ::deserialize_reader(reader) @@ -475,14 +465,14 @@ where }?; match flag { 0 => Ok(Err(if _sync { - ::deserialize_reader(reader) + E::deserialize_reader(reader) } else { - ::deserialize_reader(reader).await + E::deserialize_reader(reader).await }?)), 1 => Ok(Ok(if _sync { - ::deserialize_reader(reader) + T::deserialize_reader(reader) } else { - ::deserialize_reader(reader).await + T::deserialize_reader(reader).await }?)), _ => { let msg = format!( @@ -502,9 +492,7 @@ where )] impl BorshDeserialize for String { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { String::from_utf8(if _sync { as BorshDeserialize>::deserialize_reader(reader) @@ -522,11 +510,9 @@ impl BorshDeserialize for String { #[cfg(feature = "ascii")] pub mod ascii { //! - //! Module defines [BorshDeserialize] implementation for - //! some types from [ascii](::ascii) crate. - - #[cfg(feature = "async")] - use core::future::Future; + //! Module defines [`BorshDeserialize`] + #![cfg_attr(feature = "async", doc = " & [`BorshDeserializeAsync`]")] + //! implementation for some types from [`ascii`] crate. use async_generic::async_generic; @@ -544,9 +530,7 @@ pub mod ascii { )] impl BorshDeserialize for ascii::AsciiString { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let bytes = if _sync { as BorshDeserialize>::deserialize_reader(reader) @@ -564,9 +548,7 @@ pub mod ascii { )] impl BorshDeserialize for ascii::AsciiChar { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let byte = if _sync { ::deserialize_reader(reader) @@ -590,9 +572,7 @@ where T: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; @@ -603,21 +583,19 @@ where }?; if len == 0 { Ok(Vec::new()) - } else if let Some(vec_bytes) = if _sync { - T::vec_from_reader(len, reader) - } else { - T::vec_from_reader(len, reader).await - }? { + } else if let Some(vec_bytes) = { + let res = T::vec_from_reader(len, reader); + if _sync { res } else { res.await }? + } { Ok(vec_bytes) } else { // TODO(16): return capacity allocation when we can safely do that. let mut result = Vec::with_capacity(hint::cautious::(len)); for _ in 0..len { - result.push(if _sync { - T::deserialize_reader(reader) - } else { - T::deserialize_reader(reader).await - }?); + result.push({ + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }? + }); } Ok(result) } @@ -631,9 +609,7 @@ where )] impl BorshDeserialize for bytes::Bytes { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { as BorshDeserialize>::deserialize_reader(reader) @@ -651,9 +627,7 @@ impl BorshDeserialize for bytes::Bytes { )] impl BorshDeserialize for BytesMut { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let len = if _sync { ::deserialize_reader(reader) @@ -679,16 +653,13 @@ impl BorshDeserialize for BytesMut { )] impl BorshDeserialize for bson::oid::ObjectId { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 12]; - if _sync { - reader.read_exact(&mut buf) - } else { - reader.read_exact(&mut buf).await - }?; + { + let res = reader.read_exact(&mut buf); + if _sync { res } else { res.await }?; + } Ok(bson::oid::ObjectId::from_bytes(buf)) } } @@ -707,15 +678,12 @@ where T::Owned: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - Ok(Cow::Owned(if _sync { - T::Owned::deserialize_reader(reader) - } else { - T::Owned::deserialize_reader(reader).await - }?)) + Ok(Cow::Owned({ + let res = T::Owned::deserialize_reader(reader); + if _sync { res } else { res.await }? + })) } } @@ -730,15 +698,12 @@ where T: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let vec = if _sync { - >::deserialize_reader(reader) - } else { - >::deserialize_reader(reader).await - }?; + let vec = { + let res = >::deserialize_reader(reader); + if _sync { res } else { res.await }? + }; Ok(vec.into()) } } @@ -754,27 +719,23 @@ where T: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let vec = if _sync { - >::deserialize_reader(reader) - } else { - >::deserialize_reader(reader).await - }?; + let vec = { + let res = >::deserialize_reader(reader); + if _sync { res } else { res.await }? + }; Ok(vec.into_iter().collect::>()) } } /// Module is available if borsh is built with `features = ["std"]` or `features = ["hashbrown"]`. /// -/// Module defines [BorshDeserialize] implementation for -/// [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet). +/// Module defines [`BorshDeserialize`] +#[cfg_attr(feature = "async", doc = " & [`BorshDeserializeAsync`]")] +/// implementation for [`HashMap`](HashMap)/[`HashSet`](HashSet). #[cfg(hash_collections)] pub mod hashes { - #[cfg(feature = "async")] - use core::future::Future; use core::hash::{BuildHasher, Hash}; use async_generic::async_generic; @@ -809,19 +770,16 @@ pub mod hashes { H: BuildHasher + Default, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the elements // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster - let vec = if _sync { - >::deserialize_reader(reader) - } else { - >::deserialize_reader(reader).await - }?; + let vec = { + let res = >::deserialize_reader(reader); + if _sync { res } else { res.await }? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -858,20 +816,17 @@ pub mod hashes { H: BuildHasher + Default, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the entries // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster - let vec = if _sync { - >::deserialize_reader(reader) - } else { - >::deserialize_reader(reader).await - }?; + let vec = { + let res = >::deserialize_reader(reader); + if _sync { res } else { res.await }? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -905,19 +860,16 @@ where T: BorshDeserialize + Ord, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the elements // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster - let vec = if _sync { - >::deserialize_reader(reader) - } else { - >::deserialize_reader(reader).await - }?; + let vec = { + let res = >::deserialize_reader(reader); + if _sync { res } else { res.await }? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -953,20 +905,17 @@ where V: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; // NOTE: deserialize-as-you-go approach as once was in HashSet is better in the sense // that it allows to fail early, and not allocate memory for all the entries // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster - let vec = if _sync { - as BorshDeserialize>::deserialize_reader(reader) - } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await - }?; + let vec = { + let res = >::deserialize_reader(reader); + if _sync { res } else { res.await }? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 @@ -997,9 +946,7 @@ where )] impl BorshDeserialize for std::net::SocketAddr { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let kind = if _sync { ::deserialize_reader(reader) @@ -1034,9 +981,7 @@ impl BorshDeserialize for std::net::SocketAddr { )] impl BorshDeserialize for std::net::IpAddr { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let kind = if _sync { ::deserialize_reader(reader) @@ -1071,9 +1016,7 @@ impl BorshDeserialize for std::net::IpAddr { )] impl BorshDeserialize for std::net::SocketAddrV4 { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { ::deserialize_reader(reader) @@ -1096,9 +1039,7 @@ impl BorshDeserialize for std::net::SocketAddrV4 { )] impl BorshDeserialize for std::net::SocketAddrV6 { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { ::deserialize_reader(reader) @@ -1121,9 +1062,7 @@ impl BorshDeserialize for std::net::SocketAddrV6 { )] impl BorshDeserialize for std::net::Ipv4Addr { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 4]; let res = reader.read_exact(&mut buf); @@ -1140,9 +1079,7 @@ impl BorshDeserialize for std::net::Ipv4Addr { )] impl BorshDeserialize for std::net::Ipv6Addr { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 16]; let res = reader.read_exact(&mut buf); @@ -1167,16 +1104,12 @@ where T::Owned: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - Ok(if _sync { - ::deserialize_reader(reader) - } else { - ::deserialize_reader(reader).await - }? - .into()) + Ok({ + let res = T::Owned::deserialize_reader(reader); + if _sync { res } else { res.await }?.into() + }) } } @@ -1317,9 +1250,7 @@ fn array_deserialization_doesnt_leak() { async_trait )] impl BorshDeserialize for MyType { - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let val = if _sync { ::deserialize_reader(reader) @@ -1388,9 +1319,7 @@ macro_rules! impl_tuple { $($name: BorshDeserialize,)+ { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { Ok(if _sync { ($(<$name as BorshDeserialize>::deserialize_reader(reader)?,)+) @@ -1436,15 +1365,12 @@ macro_rules! impl_range { )] impl BorshDeserialize for core::ops::$type { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let [$($side,)*] = if _sync { - <[T; $n] as BorshDeserialize>::deserialize_reader(reader) - } else { - <[T; $n] as BorshDeserializeAsync>::deserialize_reader(reader).await - }?; + let [$($side,)*] = { + let res = <[T; $n]>::deserialize_reader(reader); + if _sync { res } else { res.await }? + }; Ok($make) } } @@ -1461,11 +1387,9 @@ impl_range!(RangeToInclusive, ..=end, 1, end); #[cfg(feature = "rc")] pub mod rc { //! - //! Module defines [BorshDeserialize] implementation for - //! [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). - - #[cfg(feature = "async")] - use core::future::Future; + //! Module defines [`BorshDeserialize`] + #![cfg_attr(feature = "async", doc = " & [`BorshDeserializeAsync`]")] + //! implementation for [`alloc::rc::Rc`](Rc) and [`alloc::sync::Arc`](Arc). use async_generic::async_generic; @@ -1509,16 +1433,12 @@ pub mod rc { Box: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - Ok(if _sync { - >::deserialize_reader(reader) - } else { - >::deserialize_reader(reader).await - }? - .into()) + Ok({ + let res = >::deserialize_reader(reader); + if _sync { res } else { res.await }?.into() + }) } } } @@ -1539,49 +1459,193 @@ impl BorshDeserialize for PhantomData { #[async_generic( #[cfg(feature = "async")] - async_trait + async_trait where T: BorshDeserializeAsync + Copy, )] -impl BorshDeserialize for core::cell::Cell +impl BorshDeserialize for core::cell::Cell where T: BorshDeserialize + Copy, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - if _sync { - T::deserialize_reader(reader) - } else { - T::deserialize_reader(reader).await - } - .map(core::cell::Cell::new) + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(core::cell::Cell::new) } } #[async_generic( #[cfg(feature = "async")] - async_trait + async_trait where T: BorshDeserializeAsync, )] -impl BorshDeserialize for core::cell::RefCell +impl BorshDeserialize for core::cell::RefCell where T: BorshDeserialize, { #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] + #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - if _sync { - T::deserialize_reader(reader) - } else { - T::deserialize_reader(reader).await - } - .map(core::cell::RefCell::new) + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(core::cell::RefCell::new) + } +} + +#[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for std::sync::Mutex +where + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(std::sync::Mutex::new) + } +} + +#[cfg(feature = "std")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for std::sync::RwLock +where + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(std::sync::RwLock::new) + } +} + +#[cfg(feature = "lock_api")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + Raw: lock_api::RawMutex + Send, + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for lock_api::Mutex +where + Raw: lock_api::RawMutex, + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(lock_api::Mutex::new) + } +} + +#[cfg(feature = "lock_api")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + Raw: lock_api::RawRwLock + Send, + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for lock_api::RwLock +where + Raw: lock_api::RawRwLock, + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(lock_api::RwLock::new) + } +} + +#[cfg(feature = "tokio-sync")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for tokio::sync::Mutex +where + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(tokio::sync::Mutex::new) + } +} + +#[cfg(feature = "tokio-sync")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for tokio::sync::RwLock +where + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(tokio::sync::RwLock::new) + } +} + +#[cfg(feature = "async-std-sync")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for async_std::sync::Mutex +where + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(async_std::sync::Mutex::new) + } +} + +#[cfg(feature = "async-std-sync")] +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshDeserializeAsync, +)] +impl BorshDeserialize for async_std::sync::RwLock +where + T: BorshDeserialize +{ + #[inline] + #[async_generic(async_signature(reader: &mut R) -> Result)] + fn deserialize_reader(reader: &mut R) -> Result { + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }.map(async_std::sync::RwLock::new) } } @@ -1649,9 +1713,5 @@ pub fn from_slice(v: &[u8]) -> Result { async_signature[impl_fut]<'a, R: AsyncRead, T: BorshDeserializeAsync + 'a>(reader: &'a mut R) -> impl Future> + Send + 'a )] pub fn from_reader(reader: &mut R) -> Result { - if _sync { - T::try_from_reader(reader) - } else { - T::try_from_reader(reader) - } + T::try_from_reader(reader) } diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 76049fdc6..d1e1c68a2 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -204,9 +204,7 @@ macro_rules! impl_for_float { )] impl BorshSerialize for $type { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { if self.is_nan() { return Err(Error::new(ErrorKind::InvalidData, FLOAT_NAN_ERR)); @@ -255,9 +253,7 @@ where T: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { match self { None => { @@ -293,9 +289,7 @@ where E: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { match self { Err(e) => { @@ -361,8 +355,9 @@ impl BorshSerialize for String { #[cfg(feature = "ascii")] pub mod ascii { //! - //! Module defines [BorshSerialize] implementation for - //! some types from [ascii](::ascii) crate. + //! Module defines [`BorshSerialize`] + #![cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] + //! implementation for some types from [`ascii`] crate. #[cfg(feature = "async")] use core::future::Future; @@ -435,10 +430,7 @@ pub mod ascii { #[inline] #[async_generic( #[cfg(feature = "async")] - async_signature( - data: &[T], - writer: &mut W - ) -> Result<()> + async_signature(data: &[T], writer: &mut W) -> Result<()> )] fn serialize_slice(data: &[T], writer: &mut W) -> Result<()> { if let Some(u8_slice) = T::u8_slice(data) { @@ -470,9 +462,7 @@ where T: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { let len = u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidData)?; if _sync { @@ -539,9 +529,7 @@ where T: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; let slice = self.as_slice(); @@ -633,9 +621,7 @@ where T: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -664,9 +650,7 @@ where T: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -691,11 +675,9 @@ where /// /// Module defines [`BorshSerialize`] #[cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] -/// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). +/// implementation for [`HashMap`]/[`HashSet`]. #[cfg(hash_collections)] pub mod hashes { - #[cfg(feature = "async")] - use core::future::Future; use core::{convert::TryFrom, hash::BuildHasher}; use async_generic::async_generic; @@ -727,9 +709,7 @@ pub mod hashes { H: BuildHasher, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -765,9 +745,7 @@ pub mod hashes { H: BuildHasher, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -804,9 +782,7 @@ where V: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; // NOTE: BTreeMap iterates over the entries that are sorted by key, so the serialization @@ -842,9 +818,7 @@ where T: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; // NOTE: BTreeSet iterates over the items that are sorted, so the serialization result will @@ -873,9 +847,7 @@ where )] impl BorshSerialize for std::net::SocketAddr { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { match self { std::net::SocketAddr::V4(addr) => { @@ -907,9 +879,7 @@ impl BorshSerialize for std::net::SocketAddr { )] impl BorshSerialize for std::net::SocketAddrV4 { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { BorshSerialize::serialize(self.ip(), writer)?; @@ -928,9 +898,7 @@ impl BorshSerialize for std::net::SocketAddrV4 { )] impl BorshSerialize for std::net::SocketAddrV6 { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { BorshSerialize::serialize(self.ip(), writer)?; @@ -1001,9 +969,7 @@ impl BorshSerialize for std::net::Ipv6Addr { )] impl BorshSerialize for std::net::IpAddr { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { match self { std::net::IpAddr::V4(ipv4) => { @@ -1060,9 +1026,7 @@ where T: BorshSerialize, { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { if N == 0 { Ok(()) @@ -1094,7 +1058,7 @@ macro_rules! impl_tuple { impl BorshSerialize for $name { #[inline] #[async_generic( - async_signature[ready]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[ready]<'a, W: AsyncWrite>(&'a self, _: &'a mut W) -> impl Future> + Send + 'a )] fn serialize(&self, _: &mut W) -> Result<()> { Ok(()) @@ -1114,9 +1078,7 @@ macro_rules! impl_tuple { $($name: BorshSerialize,)+ { #[inline] - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { $(BorshSerialize::serialize(&self.$idx, writer)?;)+ @@ -1155,11 +1117,22 @@ impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T macro_rules! impl_range { ($type:ident, $this:ident, $($field:expr),*) => { + #[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshSerializeAsync, + )] impl BorshSerialize for core::ops::$type { #[inline] + #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] fn serialize(&self, writer: &mut W) -> Result<()> { let $this = self; - $( $field.serialize(writer)?; )* + if _sync { + $( let _ = $field.serialize(writer)?; )* + } else { + $( let _ = $field.serialize(writer).await?; )* + } Ok(()) } } @@ -1176,8 +1149,18 @@ impl_range!(RangeToInclusive, this, &this.end); #[cfg(feature = "rc")] pub mod rc { //! - //! Module defines [BorshSerialize] implementation for - //! [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). + //! Module defines [`BorshSerialize`] + #![cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] + //! implementation for [`Rc`] and [`Arc`]. + + #[cfg(feature = "async")] + use core::future::Future; + + #[cfg(feature = "async")] + use async_generic::async_generic; + + #[cfg(feature = "async")] + use super::{AsyncWrite, BorshSerializeAsync}; use crate::{ __private::maybestd::{rc::Rc, sync::Arc}, io::{Result, Write}, @@ -1202,14 +1185,34 @@ pub mod rc { /// the contents of the `Arc` each time the `Arc` is referenced within the /// data structure. Serialization will not attempt to deduplicate these /// repeated data. + #[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: BorshSerializeAsync + ?Sized + Send, + )] impl BorshSerialize for Arc { + #[inline] + #[async_generic( + async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + )] fn serialize(&self, writer: &mut W) -> Result<()> { (**self).serialize(writer) } } } +#[async_generic( + #[cfg(feature = "async")] + async_trait + where + T: ?Sized + Sync, +)] impl BorshSerialize for PhantomData { + #[inline] + #[async_generic( + async_signature[ready]<'a, W: AsyncWrite>(&'a self, _: &'a mut W) -> impl Future> + Send + )] fn serialize(&self, _: &mut W) -> Result<()> { Ok(()) } @@ -1217,16 +1220,17 @@ impl BorshSerialize for PhantomData { impl BorshSerialize for core::cell::Cell where - T: BorshSerialize + Copy, + T: BorshSerialize + ?Sized + Copy, { + #[inline] fn serialize(&self, writer: &mut W) -> Result<()> { - ::serialize(&self.get(), writer) + T::serialize(&self.get(), writer) } } impl BorshSerialize for core::cell::RefCell where - T: BorshSerialize + Sized, + T: BorshSerialize + ?Sized, { fn serialize(&self, writer: &mut W) -> Result<()> { match self.try_borrow() { @@ -1235,3 +1239,95 @@ where } } } + +#[cfg(feature = "std")] +impl BorshSerialize for std::sync::Mutex +where + T: BorshSerialize + ?Sized, +{ + fn serialize(&self, writer: &mut W) -> Result<()> { + let guard = self + .lock() + .map_err(|_| Error::new(ErrorKind::Other, "mutex poisoned"))?; + guard.serialize(writer) + } +} + +#[cfg(feature = "std")] +impl BorshSerialize for std::sync::RwLock +where + T: BorshSerialize + ?Sized, +{ + fn serialize(&self, writer: &mut W) -> Result<()> { + let guard = self + .read() + .map_err(|_| Error::new(ErrorKind::Other, "rwlock poisoned"))?; + guard.serialize(writer) + } +} + +#[cfg(feature = "async-std-sync")] +impl BorshSerializeAsync for async_std::sync::Mutex +where + T: BorshSerializeAsync + ?Sized + Send, +{ + async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { + let guard = self.lock().await; + guard.serialize(writer).await + } +} + +#[cfg(feature = "async-std-sync")] +impl BorshSerializeAsync for async_std::sync::RwLock +where + T: BorshSerializeAsync + ?Sized + Send, +{ + async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { + let guard = self.read().await; + guard.serialize(writer).await + } +} + +#[cfg(feature = "lock_api")] +impl BorshSerialize for lock_api::Mutex +where + R: lock_api::RawMutex, + T: BorshSerialize + ?Sized, +{ + fn serialize(&self, writer: &mut W) -> Result<()> { + self.lock().serialize(writer) + } +} + +#[cfg(feature = "lock_api")] +impl BorshSerialize for lock_api::RwLock +where + R: lock_api::RawRwLock, + T: BorshSerialize + ?Sized, +{ + fn serialize(&self, writer: &mut W) -> Result<()> { + self.read().serialize(writer) + } +} + +#[cfg(feature = "tokio-sync")] +impl BorshSerializeAsync for tokio::sync::Mutex +where + T: BorshSerializeAsync + ?Sized + Send, +{ + async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { + let guard = self.lock().await; + guard.serialize(writer).await + } +} + +#[cfg(feature = "tokio-sync")] +impl BorshSerializeAsync for tokio::sync::RwLock +where + T: BorshSerializeAsync + ?Sized + Send, +{ + async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { + let guard = self.read().await; + guard.serialize(writer).await + } +} diff --git a/rustfmt.toml b/rustfmt.toml index 030dbec30..4d94d105b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,4 +1,4 @@ -edition = "2018" +edition = "2021" unstable_features = true group_imports = "StdExternalCrate" imports_granularity = "Crate" \ No newline at end of file From e322cb5315e96a245baf165c693a048ec0d9209b Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 17:35:01 +0200 Subject: [PATCH 14/69] Fix docs --- borsh/src/async_io.rs | 5 ++++- borsh/src/de/mod.rs | 24 ++++++++++++------------ borsh/src/ser/mod.rs | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index 73ebbcf7e..90eef618f 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -111,7 +111,10 @@ pub trait AsyncRead: Unpin + Send { // #[async_trait] impl AsyncRead for R { #[inline] - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> impl Future> + Send + 'a { + fn read<'a>( + &'a mut self, + buf: &'a mut [u8], + ) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read(self, buf) } diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 40ef037d9..72b624dba 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -290,9 +290,9 @@ impl_for_integer!(u128, read_u128); macro_rules! impl_for_nonzero_integer { ($type: ty, $repr: ty) => { #[async_generic( - #[cfg(feature = "async")] - async_trait - )] + #[cfg(feature = "async")] + async_trait + )] impl BorshDeserialize for $type { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -733,7 +733,7 @@ where /// /// Module defines [`BorshDeserialize`] #[cfg_attr(feature = "async", doc = " & [`BorshDeserializeAsync`]")] -/// implementation for [`HashMap`](HashMap)/[`HashSet`](HashSet). +/// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { use core::hash::{BuildHasher, Hash}; @@ -1502,7 +1502,7 @@ where )] impl BorshDeserialize for std::sync::Mutex where - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1521,7 +1521,7 @@ where )] impl BorshDeserialize for std::sync::RwLock where - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1542,7 +1542,7 @@ where impl BorshDeserialize for lock_api::Mutex where Raw: lock_api::RawMutex, - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1563,7 +1563,7 @@ where impl BorshDeserialize for lock_api::RwLock where Raw: lock_api::RawRwLock, - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1582,7 +1582,7 @@ where )] impl BorshDeserialize for tokio::sync::Mutex where - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1601,7 +1601,7 @@ where )] impl BorshDeserialize for tokio::sync::RwLock where - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1620,7 +1620,7 @@ where )] impl BorshDeserialize for async_std::sync::Mutex where - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1639,7 +1639,7 @@ where )] impl BorshDeserialize for async_std::sync::RwLock where - T: BorshDeserialize + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index d1e1c68a2..5239b507f 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -675,7 +675,7 @@ where /// /// Module defines [`BorshSerialize`] #[cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] -/// implementation for [`HashMap`]/[`HashSet`]. +/// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { use core::{convert::TryFrom, hash::BuildHasher}; From 6e250a5457578d0b24c2ab44080fb7f5112146a8 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 17:35:37 +0200 Subject: [PATCH 15/69] set patch `syn` version --- borsh-derive/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/borsh-derive/Cargo.toml b/borsh-derive/Cargo.toml index c0200bc07..4596d6d42 100644 --- a/borsh-derive/Cargo.toml +++ b/borsh-derive/Cargo.toml @@ -18,14 +18,14 @@ exclude = ["*.snap"] proc-macro = true [dependencies] -syn = { version = "2.0", features = ["full", "fold"] } +syn = { version = "2.0.96", features = ["full", "fold"] } proc-macro-crate = "3" proc-macro2 = "1.0" quote = "1.0" once_cell = "1.18.0" [dev-dependencies] -syn = { version = "2.0", features = ["parsing"] } +syn = { version = "2.0.96", features = ["parsing"] } prettyplease = "0.2.9" insta = "1.29.0" From 0d0d55098a4969c7f4bfc036845f921faed98c0c Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 19:39:16 +0200 Subject: [PATCH 16/69] Manually declare async trait variants. Update `async_generic` usage --- borsh/Cargo.toml | 1 + borsh/src/de/mod.rs | 235 ++++++++++++++++++++++++++------------- borsh/src/lib.rs | 4 + borsh/src/ser/helpers.rs | 30 +++-- borsh/src/ser/mod.rs | 138 +++++++++++++++-------- 5 files changed, 275 insertions(+), 133 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 725a80ffa..f3045a2fa 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -47,6 +47,7 @@ async-std = { version = "1", default-features = false, features = ["std"], optio lock_api = { version = "0.4", optional = true } [dev-dependencies] +tokio-test = "0.4.4" insta = "1.29.0" serde_json = { version = "1" } diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 72b624dba..8befe2961 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -38,10 +38,6 @@ const ERROR_INVALID_ZERO_VALUE: &str = "Expected a non-zero value"; const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order"; /// A data-structure that can be de-serialized from binary format by NBOR. -#[async_generic( - #[cfg(feature = "async")] - async_trait: Sized + Send -)] pub trait BorshDeserialize: Sized { /// Deserializes this instance from a given slice of bytes. /// Updates the buffer to point at the remaining bytes. @@ -49,9 +45,6 @@ pub trait BorshDeserialize: Sized { Self::deserialize_reader(&mut *buf) } - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] fn deserialize_reader(reader: &mut R) -> Result; /// Deserialize this instance from a slice of bytes. @@ -64,20 +57,11 @@ pub trait BorshDeserialize: Sized { Ok(result) } - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] fn try_from_reader(reader: &mut R) -> Result { - let result = if _sync { - Self::deserialize_reader(reader) - } else { - Self::deserialize_reader(reader).await - }?; + let result = Self::deserialize_reader(reader)?; let mut buf = [0u8; 1]; - let res = reader.read_exact(&mut buf); - let res = if _sync { res } else { res.await }; - match res { + match reader.read_exact(&mut buf) { Err(f) if f.kind() == ErrorKind::UnexpectedEof => Ok(result), _ => Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)), } @@ -85,9 +69,6 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] - #[async_generic( - async_signature[ready](len: u32, reader: &mut R) -> impl Future>>> + Send - )] fn vec_from_reader(len: u32, reader: &mut R) -> Result>> { let _ = len; let _ = reader; @@ -96,25 +77,60 @@ pub trait BorshDeserialize: Sized { #[inline] #[doc(hidden)] - #[async_generic( - async_signature[ready](reader: &mut R) -> impl Future>> + Send - )] fn array_from_reader(reader: &mut R) -> Result> { let _ = reader; Ok(None) } } +/// A data-structure that can be asynchronously de-serialized from binary format by NBOR. +#[cfg(feature = "async")] +pub trait BorshDeserializeAsync: Sized + Send { + fn deserialize_reader( + reader: &mut R, + ) -> impl Future> + Send; + + fn try_from_reader(reader: &mut R) -> impl Future> + Send { + async move { + let result = { Self::deserialize_reader(reader).await }?; + + let mut buf = [0u8; 1]; + let res = reader.read_exact(&mut buf); + let res = { res.await }; + match res { + Err(f) if f.kind() == ErrorKind::UnexpectedEof => Ok(result), + _ => Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)), + } + } + } + + #[inline] + #[doc(hidden)] + fn vec_from_reader( + len: u32, + reader: &mut R, + ) -> impl Future>>> + Send { + let _ = len; + let _ = reader; + core::future::ready(Ok(None)) + } + + #[inline] + #[doc(hidden)] + fn array_from_reader( + reader: &mut R, + ) -> impl Future>> + Send { + let _ = reader; + core::future::ready(Ok(None)) + } +} + /// Additional methods offered on enums which is used by `[derive(BorshDeserialize)]`. -#[async_generic( - #[cfg(feature = "async")] - async_trait: Sized + Send -)] pub trait EnumExt: BorshDeserialize { /// Deserialises given variant of an enum from the reader. /// /// This may be used to perform validation or filtering based on what - /// variant is being deserialised. + /// variant is being deserialized. /// /// ``` /// use borsh::BorshDeserialize; @@ -164,12 +180,73 @@ pub trait EnumExt: BorshDeserialize { /// # #[cfg(feature = "derive")] /// assert!(from_slice::(&data[..]).is_err()); /// ``` - #[async_generic( - async_signature[impl_fut](reader: &mut R, tag: u8) -> impl Future> + Send - )] fn deserialize_variant(reader: &mut R, tag: u8) -> Result; } +/// Additional methods offered on enums which is used by `[derive(BorshDeserializeAsync)]`. +#[cfg(feature = "async")] +pub trait EnumExtAsync: BorshDeserializeAsync { + /// Deserialises given variant of an enum from the async reader. + /// + /// This may be used to perform validation or filtering based on what + /// variant is being deserialized. + /// + /// ``` + /// # tokio_test::block_on(async { + /// use borsh::BorshDeserializeAsync; + /// use borsh::de::EnumExtAsync as _; + /// + /// /// derive is only available if borsh is built with `features = ["derive"]` + /// # #[cfg(feature = "derive")] + /// #[derive(Debug, PartialEq, Eq, BorshDeserializeAsync)] + /// enum MyEnum { + /// Zero, + /// One(u8), + /// Many(Vec) + /// } + /// + /// # #[cfg(feature = "derive")] + /// #[derive(Debug, PartialEq, Eq)] + /// struct OneOrZero(MyEnum); + /// + /// # #[cfg(feature = "derive")] + /// impl borsh::de::BorshDeserializeAsync for OneOrZero { + /// async fn deserialize_reader( + /// reader: &mut R, + /// ) -> borsh::io::Result { + /// use borsh::de::EnumExtAsync; + /// let tag = u8::deserialize_reader(reader).await?; + /// if tag == 2 { + /// Err(borsh::io::Error::new( + /// borsh::io::ErrorKind::InvalidData, + /// "MyEnum::Many not allowed here", + /// )) + /// } else { + /// MyEnum::deserialize_variant(reader, tag).await.map(Self) + /// } + /// } + /// } + /// + /// use borsh::from_slice; + /// 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); + /// + /// 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()); + /// # }); + /// ``` + fn deserialize_variant( + reader: &mut R, + tag: u8, + ) -> impl Future> + Send; +} + fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { if e.kind() == ErrorKind::UnexpectedEof { Error::new(ErrorKind::InvalidData, ERROR_UNEXPECTED_LENGTH_OF_INPUT) @@ -180,7 +257,7 @@ fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for u8 { #[inline] @@ -254,7 +331,7 @@ macro_rules! impl_for_integer { ($type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for $type { #[inline] @@ -290,9 +367,9 @@ impl_for_integer!(u128, read_u128); macro_rules! impl_for_nonzero_integer { ($type: ty, $repr: ty) => { #[async_generic( - #[cfg(feature = "async")] - async_trait - )] + #[cfg(feature = "async")] + async_variant + )] impl BorshDeserialize for $type { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -325,7 +402,7 @@ macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for $type { #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -352,7 +429,7 @@ macro_rules! impl_for_float { ($type: ident, $int_type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for $type { #[inline] @@ -384,7 +461,7 @@ impl_for_float!(f64, u64, read_f64); #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for bool { #[inline] @@ -408,7 +485,7 @@ impl BorshDeserialize for bool { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -445,7 +522,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, E: BorshDeserializeAsync, @@ -488,7 +565,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for String { #[inline] @@ -526,7 +603,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for ascii::AsciiString { #[inline] @@ -544,7 +621,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for ascii::AsciiChar { #[inline] @@ -563,7 +640,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -605,7 +682,7 @@ where #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for bytes::Bytes { #[inline] @@ -623,7 +700,7 @@ impl BorshDeserialize for bytes::Bytes { #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for BytesMut { #[inline] @@ -649,7 +726,7 @@ impl BorshDeserialize for BytesMut { #[cfg(feature = "bson")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for bson::oid::ObjectId { #[inline] @@ -666,7 +743,7 @@ impl BorshDeserialize for bson::oid::ObjectId { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: ToOwned + ?Sized, T::Owned: BorshDeserializeAsync, @@ -689,7 +766,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -710,7 +787,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -759,7 +836,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync + Eq + Hash + Ord, H: BuildHasher + Default + Send, @@ -803,7 +880,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where K: BorshDeserializeAsync + Eq + Hash + Ord, V: BorshDeserializeAsync, @@ -851,7 +928,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync + Ord, )] @@ -894,7 +971,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where K: BorshDeserializeAsync + Ord, V: BorshDeserializeAsync, @@ -942,7 +1019,7 @@ where #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for std::net::SocketAddr { #[inline] @@ -977,7 +1054,7 @@ impl BorshDeserialize for std::net::SocketAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for std::net::IpAddr { #[inline] @@ -1012,7 +1089,7 @@ impl BorshDeserialize for std::net::IpAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for std::net::SocketAddrV4 { #[inline] @@ -1035,7 +1112,7 @@ impl BorshDeserialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for std::net::SocketAddrV6 { #[inline] @@ -1058,7 +1135,7 @@ impl BorshDeserialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for std::net::Ipv4Addr { #[inline] @@ -1075,7 +1152,7 @@ impl BorshDeserialize for std::net::Ipv4Addr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for std::net::Ipv6Addr { #[inline] @@ -1091,7 +1168,7 @@ impl BorshDeserialize for std::net::Ipv6Addr { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where U: Into> + Borrow, T: ToOwned + ?Sized + Send, @@ -1247,7 +1324,7 @@ fn array_deserialization_doesnt_leak() { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for MyType { #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1294,7 +1371,7 @@ macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for $name { #[inline] @@ -1310,7 +1387,7 @@ macro_rules! impl_tuple { ($($name:ident)+) => { #[async_generic( #[cfg(feature = "async")] - async_trait<$($name),+> + async_variant<$($name),+> where $($name: BorshDeserializeAsync,)+ )] @@ -1359,7 +1436,7 @@ macro_rules! impl_range { ($type:ident, $make:expr, $n: literal, $($side:ident),*) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -1423,7 +1500,7 @@ pub mod rc { /// will end up with a strong count of 1. #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where Box: BorshDeserializeAsync, Self: Send, @@ -1445,7 +1522,7 @@ pub mod rc { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshDeserialize for PhantomData { #[inline] @@ -1459,7 +1536,7 @@ impl BorshDeserialize for PhantomData { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync + Copy, )] @@ -1477,7 +1554,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -1496,7 +1573,7 @@ where #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -1515,7 +1592,7 @@ where #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -1534,7 +1611,7 @@ where #[cfg(feature = "lock_api")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where Raw: lock_api::RawMutex + Send, T: BorshDeserializeAsync, @@ -1555,7 +1632,7 @@ where #[cfg(feature = "lock_api")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where Raw: lock_api::RawRwLock + Send, T: BorshDeserializeAsync, @@ -1576,7 +1653,7 @@ where #[cfg(feature = "tokio-sync")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -1595,7 +1672,7 @@ where #[cfg(feature = "tokio-sync")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -1614,7 +1691,7 @@ where #[cfg(feature = "async-std-sync")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] @@ -1633,7 +1710,7 @@ where #[cfg(feature = "async-std-sync")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshDeserializeAsync, )] diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index dcda22db5..ca0fca5c0 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -25,12 +25,16 @@ pub(crate) mod schema_helpers; pub mod ser; pub use de::{from_reader, from_slice, BorshDeserialize}; +#[cfg(feature = "async")] +pub use de::{from_reader_async, BorshDeserializeAsync}; #[cfg(feature = "unstable__schema")] pub use schema::BorshSchema; #[cfg(feature = "unstable__schema")] pub use schema_helpers::{ max_serialized_size, schema_container_of, try_from_slice_with_schema, try_to_vec_with_schema, }; +#[cfg(feature = "async")] +pub use ser::{helpers::to_writer_async, BorshSerializeAsync}; pub use ser::{ helpers::{object_length, to_vec, to_writer}, BorshSerialize, diff --git a/borsh/src/ser/helpers.rs b/borsh/src/ser/helpers.rs index 699f08843..6f9061cb8 100644 --- a/borsh/src/ser/helpers.rs +++ b/borsh/src/ser/helpers.rs @@ -1,3 +1,7 @@ +use async_generic::async_generic; + +#[cfg(feature = "async")] +use crate::{async_io::AsyncWrite, BorshSerializeAsync}; use crate::{ BorshSerialize, __private::maybestd::vec::Vec, @@ -24,17 +28,29 @@ where /// Serializes an object directly into a `Writer`. /// # Example /// -/// ``` -/// # #[cfg(feature = "std")] -/// let stderr = std::io::stderr(); -/// # #[cfg(feature = "std")] -/// assert_eq!((), borsh::to_writer(&stderr, "hello_0x0a").unwrap()); -/// ``` +#[async_generic( + /// ``` + /// # #[cfg(feature = "std")] + /// let stderr = std::io::stderr(); + /// # #[cfg(feature = "std")] + /// assert_eq!((), borsh::to_writer(&stderr, "hello_0x0a").unwrap()); + /// ``` + sync_signature; + #[cfg(feature = "async")] + async_signature(mut writer: W, value: &T) -> Result<()> + where + T: BorshSerializeAsync + ?Sized, +)] pub fn to_writer(mut writer: W, value: &T) -> Result<()> where T: BorshSerialize + ?Sized, { - value.serialize(&mut writer) + let res = value.serialize(&mut writer); + if _sync { + res + } else { + res.await + } } /// Serializes an object without allocation to compute and return its length diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 5239b507f..ec88b00fc 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -34,7 +34,6 @@ const FLOAT_NAN_ERR: &str = "For portability reasons we do not allow to serializ /// value: String, /// } /// -/// /// # #[cfg(feature = "derive")] /// let x = MyBorshSerializableStruct { value: "hello".to_owned() }; /// let mut buffer: Vec = Vec::new(); @@ -55,14 +54,7 @@ const FLOAT_NAN_ERR: &str = "For portability reasons we do not allow to serializ /// # #[cfg(feature = "derive")] /// x.serialize(&mut buffer_slice_enough_for_the_data).unwrap(); /// ``` -#[async_generic( - #[cfg(feature = "async")] - async_trait(copy_sync): Sync -)] pub trait BorshSerialize { - #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a - )] fn serialize(&self, writer: &mut W) -> Result<()>; #[inline] @@ -76,9 +68,61 @@ pub trait BorshSerialize { } } +/// A data-structure that can be serialized into binary format by NBOR. +/// +/// ``` +/// # tokio_test::block_on(async { +/// use borsh::BorshSerializeAsync; +/// +/// /// derive is only available if borsh is built with `features = ["derive"]` +/// # #[cfg(feature = "derive")] +/// #[derive(BorshSerializeAsync)] +/// struct MyBorshSerializableStruct { +/// value: String, +/// } +/// +/// # #[cfg(feature = "derive")] +/// let x = MyBorshSerializableStruct { value: "hello".to_owned() }; +/// let mut buffer: Vec = Vec::new(); +/// # #[cfg(feature = "derive")] +/// x.serialize(&mut buffer).await.unwrap(); +/// # #[cfg(feature = "derive")] +/// let single_serialized_buffer_len = buffer.len(); +/// +/// # #[cfg(feature = "derive")] +/// x.serialize(&mut buffer).unwrap(); +/// # #[cfg(feature = "derive")] +/// 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).unwrap(); +/// # }) +/// ``` +#[cfg(feature = "async")] +pub trait BorshSerializeAsync: Sync { + fn serialize<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a; + + #[inline] + #[doc(hidden)] + fn u8_slice(slice: &[Self]) -> Option<&[u8]> + where + Self: Sized, + { + let _ = slice; + None + } +} + #[async_generic( #[cfg(feature = "async")] - async_trait(copy_sync) + async_variant(copy_sync) )] impl BorshSerialize for u8 { #[inline] @@ -103,7 +147,7 @@ macro_rules! impl_for_integer { ($type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for $type { #[inline] @@ -136,7 +180,7 @@ macro_rules! impl_for_nonzero_integer { ($type: ty, $method: ident $(, $repr: ty)?) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for $type { #[inline] @@ -172,7 +216,7 @@ macro_rules! impl_for_size_integer { ($type:ty: $repr:ty, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for $type { #[inline] @@ -200,7 +244,7 @@ macro_rules! impl_for_float { ($type: ident, $method: ident) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for $type { #[inline] @@ -225,7 +269,7 @@ impl_for_float!(f64, write_f64); #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for bool { #[inline] @@ -244,7 +288,7 @@ impl BorshSerialize for bool { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync, )] @@ -278,7 +322,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync, E: BorshSerializeAsync, @@ -316,7 +360,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for str { #[inline] @@ -335,7 +379,7 @@ impl BorshSerialize for str { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for String { #[inline] @@ -371,7 +415,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for ascii::AsciiChar { #[inline] @@ -390,7 +434,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for ascii::AsciiStr { #[inline] @@ -409,7 +453,7 @@ pub mod ascii { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for ascii::AsciiString { #[inline] @@ -453,7 +497,7 @@ fn serialize_slice(data: &[T], writer: &mut W) -> R #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync + Sync, )] @@ -477,7 +521,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for &T { #[inline] @@ -495,7 +539,7 @@ impl BorshSerialize for &T { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync + ToOwned + ?Sized, ::Owned: Sync, @@ -520,7 +564,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync, )] @@ -547,7 +591,7 @@ where #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for bytes::Bytes { #[inline] @@ -567,7 +611,7 @@ impl BorshSerialize for bytes::Bytes { #[cfg(feature = "bytes")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for bytes::BytesMut { #[inline] @@ -586,7 +630,7 @@ impl BorshSerialize for bytes::BytesMut { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] #[cfg(feature = "bson")] impl BorshSerialize for bson::oid::ObjectId { @@ -612,7 +656,7 @@ impl BorshSerialize for bson::oid::ObjectId { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync, )] @@ -641,7 +685,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync, )] @@ -696,7 +740,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where K: BorshSerializeAsync + Ord, V: BorshSerializeAsync, @@ -734,7 +778,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync + Ord, H: BuildHasher + Sync, @@ -771,7 +815,7 @@ pub mod hashes { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where K: BorshSerializeAsync, V: BorshSerializeAsync, @@ -809,7 +853,7 @@ where #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync + Sync, )] @@ -843,7 +887,7 @@ where #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for std::net::SocketAddr { #[inline] @@ -875,7 +919,7 @@ impl BorshSerialize for std::net::SocketAddr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for std::net::SocketAddrV4 { #[inline] @@ -894,7 +938,7 @@ impl BorshSerialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for std::net::SocketAddrV6 { #[inline] @@ -913,7 +957,7 @@ impl BorshSerialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for std::net::Ipv4Addr { #[inline] @@ -939,7 +983,7 @@ impl BorshSerialize for std::net::Ipv4Addr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for std::net::Ipv6Addr { #[inline] @@ -965,7 +1009,7 @@ impl BorshSerialize for std::net::Ipv6Addr { #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for std::net::IpAddr { #[inline] @@ -996,7 +1040,7 @@ impl BorshSerialize for std::net::IpAddr { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync + ?Sized, )] @@ -1017,7 +1061,7 @@ impl BorshSerialize for Box { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync, )] @@ -1053,7 +1097,7 @@ macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant )] impl BorshSerialize for $name { #[inline] @@ -1069,7 +1113,7 @@ macro_rules! impl_tuple { ($($idx:tt $name:ident)+) => { #[async_generic( #[cfg(feature = "async")] - async_trait<$($name),+> + async_variant<$($name),+> where $($name: BorshSerializeAsync,)+ )] @@ -1119,7 +1163,7 @@ macro_rules! impl_range { ($type:ident, $this:ident, $($field:expr),*) => { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync, )] @@ -1187,7 +1231,7 @@ pub mod rc { /// repeated data. #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: BorshSerializeAsync + ?Sized + Send, )] @@ -1204,7 +1248,7 @@ pub mod rc { #[async_generic( #[cfg(feature = "async")] - async_trait + async_variant where T: ?Sized + Sync, )] From a677a17e11aa2453d969951f15329fbd0dd680ed Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 19:46:28 +0200 Subject: [PATCH 17/69] Fix formatting in macros --- borsh/src/de/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 8befe2961..bc06b5767 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -367,9 +367,9 @@ impl_for_integer!(u128, read_u128); macro_rules! impl_for_nonzero_integer { ($type: ty, $repr: ty) => { #[async_generic( - #[cfg(feature = "async")] - async_variant - )] + #[cfg(feature = "async")] + async_variant + )] impl BorshDeserialize for $type { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -401,9 +401,9 @@ impl_for_nonzero_integer!(core::num::NonZeroUsize, usize); macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { #[async_generic( - #[cfg(feature = "async")] - async_variant - )] + #[cfg(feature = "async")] + async_variant + )] impl BorshDeserialize for $type { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { @@ -428,9 +428,9 @@ impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); macro_rules! impl_for_float { ($type: ident, $int_type: ident, $method: ident) => { #[async_generic( - #[cfg(feature = "async")] - async_variant - )] + #[cfg(feature = "async")] + async_variant + )] impl BorshDeserialize for $type { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] From 48f7d09c81e04622fb656d22fd0dcc8f82c7df2c Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 22:43:07 +0200 Subject: [PATCH 18/69] Fixate `async-generic` commit version --- borsh/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index f3045a2fa..987792b58 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -42,6 +42,7 @@ bytes = { version = "1", optional = true } bson = { version = "2", optional = true } async-generic = { git = "https://github.com/DanikVitek/async-generic.git" } +async-generic = { git = "https://github.com/DanikVitek/async-generic.git#392e8ef432c9bf4ca381262f56e192a27136e04f" } tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } async-std = { version = "1", default-features = false, features = ["std"], optional = true } lock_api = { version = "0.4", optional = true } From d2ea4303b7c57951f6547b6d387f7ea923910310 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 22:44:35 +0200 Subject: [PATCH 19/69] Fixate `async-generic` commit version --- borsh/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 987792b58..020446ffb 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -41,7 +41,6 @@ hashbrown = { version = ">=0.11,<0.16.0", optional = true } bytes = { version = "1", optional = true } bson = { version = "2", optional = true } -async-generic = { git = "https://github.com/DanikVitek/async-generic.git" } async-generic = { git = "https://github.com/DanikVitek/async-generic.git#392e8ef432c9bf4ca381262f56e192a27136e04f" } tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } async-std = { version = "1", default-features = false, features = ["std"], optional = true } From 0c85a18dd52303b0a07fbb27d0a3be05c55a4712 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 23:09:14 +0200 Subject: [PATCH 20/69] Box errors instead of strings --- borsh/src/de/mod.rs | 62 ++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index bc06b5767..7f7a20afe 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -18,7 +18,7 @@ use crate::{ boxed::Box, collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, format, - string::{String, ToString}, + string::String, vec, vec::Vec, }, @@ -503,19 +503,17 @@ where }?; match flag { 0 => Ok(None), - 1 => Ok(Some(if _sync { - ::deserialize_reader(reader) - } else { - ::deserialize_reader(reader).await - }?)), - _ => { - let msg = format!( + 1 => Ok(Some({ + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }? + })), + _ => Err(Error::new( + ErrorKind::InvalidData, + format!( "Invalid Option representation: {}. The first byte must be 0 or 1", flag - ); - - Err(Error::new(ErrorKind::InvalidData, msg)) - } + ), + )), } } } @@ -541,24 +539,21 @@ where ::deserialize_reader(reader).await }?; match flag { - 0 => Ok(Err(if _sync { - E::deserialize_reader(reader) - } else { - E::deserialize_reader(reader).await - }?)), - 1 => Ok(Ok(if _sync { - T::deserialize_reader(reader) - } else { - T::deserialize_reader(reader).await - }?)), - _ => { - let msg = format!( + 0 => Ok(Err({ + let res = E::deserialize_reader(reader); + if _sync { res } else { res.await }? + })), + 1 => Ok(Ok({ + let res = T::deserialize_reader(reader); + if _sync { res } else { res.await }? + })), + _ => Err(Error::new( + ErrorKind::InvalidData, + format!( "Invalid Result representation: {}. The first byte must be 0 or 1", flag - ); - - Err(Error::new(ErrorKind::InvalidData, msg)) - } + ), + )), } } } @@ -576,10 +571,7 @@ impl BorshDeserialize for String { } else { as BorshDeserializeAsync>::deserialize_reader(reader).await }?) - .map_err(|err| { - let msg = err.to_string(); - Error::new(ErrorKind::InvalidData, msg) - }) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } } @@ -597,7 +589,7 @@ pub mod ascii { #[cfg(feature = "async")] use super::{AsyncRead, BorshDeserializeAsync}; use crate::{ - __private::maybestd::{string::ToString, vec::Vec}, + __private::maybestd::vec::Vec, io::{Error, ErrorKind, Read, Result}, }; @@ -615,7 +607,7 @@ pub mod ascii { as BorshDeserializeAsync>::deserialize_reader(reader).await }?; ascii::AsciiString::from_ascii(bytes) - .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } } @@ -633,7 +625,7 @@ pub mod ascii { ::deserialize_reader(reader).await }?; ascii::AsciiChar::from_ascii(byte) - .map_err(|err| Error::new(ErrorKind::InvalidData, err.to_string())) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } } } From 09735b26bc0c38705d2124198aa98b84d06e463e Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 23:28:09 +0200 Subject: [PATCH 21/69] Remove support locks and unnecessary trait bounds --- borsh/Cargo.toml | 5 -- borsh/src/de/mod.rs | 164 ++----------------------------------------- borsh/src/ser/mod.rs | 94 +------------------------ 3 files changed, 5 insertions(+), 258 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 020446ffb..ef0c1b5d6 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -44,7 +44,6 @@ bson = { version = "2", optional = true } async-generic = { git = "https://github.com/DanikVitek/async-generic.git#392e8ef432c9bf4ca381262f56e192a27136e04f" } tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } async-std = { version = "1", default-features = false, features = ["std"], optional = true } -lock_api = { version = "0.4", optional = true } [dev-dependencies] tokio-test = "0.4.4" @@ -60,11 +59,7 @@ default = ["std"] derive = ["borsh-derive"] async = [] tokio = ["async", "dep:tokio"] -tokio-sync = ["tokio", "tokio/sync"] # (de-)serialization for tokio mutex/rwlock primitives async-std = ["async", "dep:async-std"] -async-std-sync = ["async-std", "async-std/async-lock"] # (de-)serialization for async-std mutex/rwlock primitives -lock_api = [] # (de-)serialization for lock_api mutex/rwlock primitives -parking_lot = ["dep:lock_api"] # aslias for lock_api feature unstable__schema = ["derive", "borsh-derive/schema"] std = [] # Opt into impls for Rc and Arc. Serializing and deserializing these types diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 7f7a20afe..32b5fd15d 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1528,13 +1528,13 @@ impl BorshDeserialize for PhantomData { #[async_generic( #[cfg(feature = "async")] - async_variant + async_variant where - T: BorshDeserializeAsync + Copy, + T: BorshDeserializeAsync, )] -impl BorshDeserialize for core::cell::Cell +impl BorshDeserialize for core::cell::Cell where - T: BorshDeserialize + Copy, + T: BorshDeserialize, { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] @@ -1562,162 +1562,6 @@ where } } -#[cfg(feature = "std")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for std::sync::Mutex -where - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(std::sync::Mutex::new) - } -} - -#[cfg(feature = "std")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for std::sync::RwLock -where - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(std::sync::RwLock::new) - } -} - -#[cfg(feature = "lock_api")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - Raw: lock_api::RawMutex + Send, - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for lock_api::Mutex -where - Raw: lock_api::RawMutex, - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(lock_api::Mutex::new) - } -} - -#[cfg(feature = "lock_api")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - Raw: lock_api::RawRwLock + Send, - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for lock_api::RwLock -where - Raw: lock_api::RawRwLock, - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(lock_api::RwLock::new) - } -} - -#[cfg(feature = "tokio-sync")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for tokio::sync::Mutex -where - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(tokio::sync::Mutex::new) - } -} - -#[cfg(feature = "tokio-sync")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for tokio::sync::RwLock -where - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(tokio::sync::RwLock::new) - } -} - -#[cfg(feature = "async-std-sync")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for async_std::sync::Mutex -where - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(async_std::sync::Mutex::new) - } -} - -#[cfg(feature = "async-std-sync")] -#[async_generic( - #[cfg(feature = "async")] - async_variant - where - T: BorshDeserializeAsync, -)] -impl BorshDeserialize for async_std::sync::RwLock -where - T: BorshDeserialize, -{ - #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(async_std::sync::RwLock::new) - } -} - /// Deserializes an object from a slice of bytes. /// # Example /// ``` diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index ec88b00fc..ad162242b 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -1264,7 +1264,7 @@ impl BorshSerialize for PhantomData { impl BorshSerialize for core::cell::Cell where - T: BorshSerialize + ?Sized + Copy, + T: BorshSerialize + Copy, { #[inline] fn serialize(&self, writer: &mut W) -> Result<()> { @@ -1283,95 +1283,3 @@ where } } } - -#[cfg(feature = "std")] -impl BorshSerialize for std::sync::Mutex -where - T: BorshSerialize + ?Sized, -{ - fn serialize(&self, writer: &mut W) -> Result<()> { - let guard = self - .lock() - .map_err(|_| Error::new(ErrorKind::Other, "mutex poisoned"))?; - guard.serialize(writer) - } -} - -#[cfg(feature = "std")] -impl BorshSerialize for std::sync::RwLock -where - T: BorshSerialize + ?Sized, -{ - fn serialize(&self, writer: &mut W) -> Result<()> { - let guard = self - .read() - .map_err(|_| Error::new(ErrorKind::Other, "rwlock poisoned"))?; - guard.serialize(writer) - } -} - -#[cfg(feature = "async-std-sync")] -impl BorshSerializeAsync for async_std::sync::Mutex -where - T: BorshSerializeAsync + ?Sized + Send, -{ - async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { - let guard = self.lock().await; - guard.serialize(writer).await - } -} - -#[cfg(feature = "async-std-sync")] -impl BorshSerializeAsync for async_std::sync::RwLock -where - T: BorshSerializeAsync + ?Sized + Send, -{ - async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { - let guard = self.read().await; - guard.serialize(writer).await - } -} - -#[cfg(feature = "lock_api")] -impl BorshSerialize for lock_api::Mutex -where - R: lock_api::RawMutex, - T: BorshSerialize + ?Sized, -{ - fn serialize(&self, writer: &mut W) -> Result<()> { - self.lock().serialize(writer) - } -} - -#[cfg(feature = "lock_api")] -impl BorshSerialize for lock_api::RwLock -where - R: lock_api::RawRwLock, - T: BorshSerialize + ?Sized, -{ - fn serialize(&self, writer: &mut W) -> Result<()> { - self.read().serialize(writer) - } -} - -#[cfg(feature = "tokio-sync")] -impl BorshSerializeAsync for tokio::sync::Mutex -where - T: BorshSerializeAsync + ?Sized + Send, -{ - async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { - let guard = self.lock().await; - guard.serialize(writer).await - } -} - -#[cfg(feature = "tokio-sync")] -impl BorshSerializeAsync for tokio::sync::RwLock -where - T: BorshSerializeAsync + ?Sized + Send, -{ - async fn serialize<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> { - let guard = self.read().await; - guard.serialize(writer).await - } -} From f9aed6bceca49a8ba77a18dbdf80cbbe5356dbc2 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 23:30:47 +0200 Subject: [PATCH 22/69] Remove unnecessary trait bounds --- borsh/src/de/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 32b5fd15d..5f924898f 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1546,11 +1546,11 @@ where #[async_generic( #[cfg(feature = "async")] - async_variant + async_variant where T: BorshDeserializeAsync, )] -impl BorshDeserialize for core::cell::RefCell +impl BorshDeserialize for core::cell::RefCell where T: BorshDeserialize, { From ae05c3391cc91d85277a52ddac04be97d64da133 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 28 Jan 2025 23:35:08 +0200 Subject: [PATCH 23/69] Remove wrong `#[cfg]` --- borsh/src/ser/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index ad162242b..b16dedc64 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -1200,7 +1200,6 @@ pub mod rc { #[cfg(feature = "async")] use core::future::Future; - #[cfg(feature = "async")] use async_generic::async_generic; #[cfg(feature = "async")] From c57e5e6c2fc8f7849c27557f234b446225a2ea7f Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 14:23:11 +0200 Subject: [PATCH 24/69] use `cfg!` for io error creation --- borsh/src/de/mod.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 5f924898f..ffdee576c 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -18,7 +18,7 @@ use crate::{ boxed::Box, collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, format, - string::String, + string::{String, ToString}, vec, vec::Vec, }, @@ -571,7 +571,13 @@ impl BorshDeserialize for String { } else { as BorshDeserializeAsync>::deserialize_reader(reader).await }?) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + .map_err(|err| { + if cfg!(feature = "std") { + Error::new(ErrorKind::InvalidData, err) + } else { + Error::new(ErrorKind::InvalidData, err.to_string()) + } + }) } } @@ -606,8 +612,13 @@ pub mod ascii { } else { as BorshDeserializeAsync>::deserialize_reader(reader).await }?; - ascii::AsciiString::from_ascii(bytes) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + ascii::AsciiString::from_ascii(bytes).map_err(|err| { + if cfg!(feature = "std") { + Error::new(ErrorKind::InvalidData, err) + } else { + Error::new(ErrorKind::InvalidData, err.to_string()) + } + }) } } @@ -624,8 +635,13 @@ pub mod ascii { } else { ::deserialize_reader(reader).await }?; - ascii::AsciiChar::from_ascii(byte) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + ascii::AsciiChar::from_ascii(byte).map_err(|err| { + if cfg!(feature = "std") { + Error::new(ErrorKind::InvalidData, err) + } else { + Error::new(ErrorKind::InvalidData, err.to_string()) + } + }) } } } From 5da74f39bf9061a311f96c4ad76d64c7c2da53c3 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 14:24:41 +0200 Subject: [PATCH 25/69] move private `fn _new` into `pub fn new` --- borsh/src/nostd_io.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/borsh/src/nostd_io.rs b/borsh/src/nostd_io.rs index b59d385de..13aa7abb2 100644 --- a/borsh/src/nostd_io.rs +++ b/borsh/src/nostd_io.rs @@ -227,14 +227,15 @@ impl Error { /// // errors can also be created from other errors /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); /// ``` + #[inline] pub fn new>(kind: ErrorKind, error: T) -> Error { - Self::_new(kind, error.into()) - } - - fn _new(kind: ErrorKind, error: String) -> Error { - Error { - repr: Repr::Custom(Custom { kind, error }), + fn new(kind: ErrorKind, error: String) -> Error { + Error { + repr: Repr::Custom(Custom { kind, error }), + } } + + new(kind, error.into()) } /// Returns a reference to the inner error wrapped by this error (if any). From 22bb75b3853247c7159bb175b2fd439a7b37a98a Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 14:30:22 +0200 Subject: [PATCH 26/69] Fix `async-generic` revision specification --- borsh/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index ef0c1b5d6..996c63508 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -41,7 +41,7 @@ hashbrown = { version = ">=0.11,<0.16.0", optional = true } bytes = { version = "1", optional = true } bson = { version = "2", optional = true } -async-generic = { git = "https://github.com/DanikVitek/async-generic.git#392e8ef432c9bf4ca381262f56e192a27136e04f" } +async-generic = { git = "https://github.com/DanikVitek/async-generic.git", rev = "392e8ef432c9bf4ca381262f56e192a27136e04f" } tokio = { version = "1", default-features = false, features = ["io-util"], optional = true } async-std = { version = "1", default-features = false, features = ["std"], optional = true } @@ -57,7 +57,7 @@ targets = ["x86_64-unknown-linux-gnu"] [features] default = ["std"] derive = ["borsh-derive"] -async = [] +async = ["dep:pin-project-lite"] tokio = ["async", "dep:tokio"] async-std = ["async", "dep:async-std"] unstable__schema = ["derive", "borsh-derive/schema"] From dc317adef5a5f270c7965e4273efe606356a8751 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 14:33:19 +0200 Subject: [PATCH 27/69] Partial revert --- borsh/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 996c63508..3ccaeedb0 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -57,7 +57,7 @@ targets = ["x86_64-unknown-linux-gnu"] [features] default = ["std"] derive = ["borsh-derive"] -async = ["dep:pin-project-lite"] +async = [] tokio = ["async", "dep:tokio"] async-std = ["async", "dep:async-std"] unstable__schema = ["derive", "borsh-derive/schema"] From 8ff7681edc6ee8fa59f4405804129f68a51ed97e Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 15:35:26 +0200 Subject: [PATCH 28/69] replace `cfg!` with `#[cfg]` --- borsh/src/de/mod.rs | 25 ++++++++++++++++++------- borsh/src/nostd_io.rs | 2 +- borsh/src/ser/mod.rs | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index ffdee576c..4561766e3 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -10,6 +10,8 @@ use async_generic::async_generic; #[cfg(feature = "bytes")] use bytes::{BufMut, BytesMut}; +#[cfg(not(feature = "std"))] +use crate::__private::maybestd::string::ToString; #[cfg(feature = "async")] use crate::async_io::AsyncRead; use crate::{ @@ -18,7 +20,7 @@ use crate::{ boxed::Box, collections::{BTreeMap, BTreeSet, LinkedList, VecDeque}, format, - string::{String, ToString}, + string::String, vec, vec::Vec, }, @@ -572,9 +574,12 @@ impl BorshDeserialize for String { as BorshDeserializeAsync>::deserialize_reader(reader).await }?) .map_err(|err| { - if cfg!(feature = "std") { + #[cfg(feature = "std")] + { Error::new(ErrorKind::InvalidData, err) - } else { + } + #[cfg(not(feature = "std"))] + { Error::new(ErrorKind::InvalidData, err.to_string()) } }) @@ -613,9 +618,12 @@ pub mod ascii { as BorshDeserializeAsync>::deserialize_reader(reader).await }?; ascii::AsciiString::from_ascii(bytes).map_err(|err| { - if cfg!(feature = "std") { + #[cfg(feature = "std")] + { Error::new(ErrorKind::InvalidData, err) - } else { + } + #[cfg(not(feature = "std"))] + { Error::new(ErrorKind::InvalidData, err.to_string()) } }) @@ -636,9 +644,12 @@ pub mod ascii { ::deserialize_reader(reader).await }?; ascii::AsciiChar::from_ascii(byte).map_err(|err| { - if cfg!(feature = "std") { + #[cfg(feature = "std")] + { Error::new(ErrorKind::InvalidData, err) - } else { + } + #[cfg(not(feature = "std"))] + { Error::new(ErrorKind::InvalidData, err.to_string()) } }) diff --git a/borsh/src/nostd_io.rs b/borsh/src/nostd_io.rs index 13aa7abb2..280a4b930 100644 --- a/borsh/src/nostd_io.rs +++ b/borsh/src/nostd_io.rs @@ -651,7 +651,7 @@ impl Write for &mut [u8] { #[inline] fn write(&mut self, data: &[u8]) -> Result { let amt = core::cmp::min(data.len(), self.len()); - let (a, b) = core::mem::replace(self, &mut []).split_at_mut(amt); + let (a, b) = core::mem::take(self).split_at_mut(amt); a.copy_from_slice(&data[..amt]); *self = b; Ok(amt) diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index b16dedc64..9af651615 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -239,7 +239,7 @@ impl_for_size_integer!(usize: u64, write_u64); impl_for_size_integer!(isize: i64, write_i64); // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, -// and vice-versa. We disallow NaNs to avoid this issue. +// and vice versa. We disallow NaNs to avoid this issue. macro_rules! impl_for_float { ($type: ident, $method: ident) => { #[async_generic( From 97febbedab88de8a4030e13505382d61ce754c58 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 15:39:45 +0200 Subject: [PATCH 29/69] move `ToString` import --- borsh/src/de/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 4561766e3..1b50550df 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -10,8 +10,6 @@ use async_generic::async_generic; #[cfg(feature = "bytes")] use bytes::{BufMut, BytesMut}; -#[cfg(not(feature = "std"))] -use crate::__private::maybestd::string::ToString; #[cfg(feature = "async")] use crate::async_io::AsyncRead; use crate::{ @@ -580,6 +578,7 @@ impl BorshDeserialize for String { } #[cfg(not(feature = "std"))] { + use crate::__private::maybestd::string::ToString; Error::new(ErrorKind::InvalidData, err.to_string()) } }) @@ -624,6 +623,7 @@ pub mod ascii { } #[cfg(not(feature = "std"))] { + use crate::__private::maybestd::string::ToString; Error::new(ErrorKind::InvalidData, err.to_string()) } }) @@ -650,6 +650,7 @@ pub mod ascii { } #[cfg(not(feature = "std"))] { + use crate::__private::maybestd::string::ToString; Error::new(ErrorKind::InvalidData, err.to_string()) } }) From a34c3e5466d27e7d5cf2a49fbbe3bb983a19c33c Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 15:48:03 +0200 Subject: [PATCH 30/69] Fix macros formatting issues --- borsh/src/de/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 1b50550df..de4e71851 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -364,6 +364,7 @@ impl_for_integer!(u32, read_u32); impl_for_integer!(u64, read_u64); impl_for_integer!(u128, read_u128); +#[rustfmt::skip] macro_rules! impl_for_nonzero_integer { ($type: ty, $repr: ty) => { #[async_generic( @@ -398,6 +399,7 @@ impl_for_nonzero_integer!(core::num::NonZeroU64, u64); impl_for_nonzero_integer!(core::num::NonZeroU128, u128); impl_for_nonzero_integer!(core::num::NonZeroUsize, usize); +#[rustfmt::skip] macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { #[async_generic( @@ -425,6 +427,7 @@ impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, // and vice versa. We disallow NaNs to avoid this issue. +#[rustfmt::skip] macro_rules! impl_for_float { ($type: ident, $int_type: ident, $method: ident) => { #[async_generic( From b7f7fec8e15d62a19a220f0841f187d80710cf8f Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 16:17:58 +0200 Subject: [PATCH 31/69] use `crate::io::Result` --- borsh/src/async_io.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index 90eef618f..c51d6348d 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -1,5 +1,6 @@ use core::future::Future; -use std::io::Result; + +use crate::io::Result; pub trait AsyncRead: Unpin + Send { fn read<'a>(&'a mut self, buf: &'a mut [u8]) From 43bec58c1dc9a980024230293b01d3ed9691da57 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 16:30:48 +0200 Subject: [PATCH 32/69] WIP: implement derive macro for async traits --- .../src/internals/attributes/field/bounds.rs | 2 +- .../src/internals/attributes/field/mod.rs | 375 +++++++++++++----- .../src/internals/attributes/field/schema.rs | 12 +- .../src/internals/attributes/item/mod.rs | 129 +++--- borsh-derive/src/internals/attributes/mod.rs | 134 +++++-- .../src/internals/attributes/parsing.rs | 6 +- .../src/internals/deserialize/enums/mod.rs | 232 ++++++----- .../snapshots/borsh_discriminant_false-2.snap | 45 +++ .../snapshots/borsh_discriminant_false.snap | 6 +- .../snapshots/borsh_discriminant_true-2.snap | 45 +++ .../snapshots/borsh_discriminant_true.snap | 6 +- .../enums/snapshots/borsh_init_func-2.snap | 46 +++ .../enums/snapshots/borsh_init_func.snap | 6 +- .../borsh_skip_struct_variant_field-2.snap | 42 ++ .../borsh_skip_struct_variant_field.snap | 8 +- .../borsh_skip_tuple_variant_field-2.snap | 42 ++ .../borsh_skip_tuple_variant_field.snap | 8 +- .../enums/snapshots/bound_generics-2.snap | 55 +++ .../enums/snapshots/bound_generics.snap | 6 +- .../check_deserialize_with_attr-2.snap | 51 +++ .../check_deserialize_with_attr.snap | 6 +- .../generic_borsh_skip_struct_field-2.snap | 57 +++ .../generic_borsh_skip_struct_field.snap | 16 +- .../generic_borsh_skip_tuple_field-2.snap | 55 +++ .../generic_borsh_skip_tuple_field.snap | 12 +- .../generic_deserialize_bound-2.snap | 51 +++ .../snapshots/generic_deserialize_bound.snap | 6 +- .../enums/snapshots/recursive_enum-2.snap | 53 +++ .../enums/snapshots/recursive_enum.snap | 6 +- .../simple_enum_with_custom_crate-2.snap | 50 +++ .../simple_enum_with_custom_crate.snap | 6 +- .../enums/snapshots/simple_generics-2.snap | 53 +++ .../enums/snapshots/simple_generics.snap | 6 +- borsh-derive/src/internals/deserialize/mod.rs | 54 ++- .../src/internals/deserialize/structs/mod.rs | 197 ++++----- .../structs/snapshots/borsh_init_func.snap | 4 +- .../structs/snapshots/bound_generics.snap | 4 +- .../check_deserialize_with_attr.snap | 4 +- .../snapshots/generic_deserialize_bound.snap | 4 +- ...eneric_named_fields_struct_borsh_skip.snap | 10 +- .../generic_tuple_struct_borsh_skip1.snap | 10 +- .../generic_tuple_struct_borsh_skip2.snap | 8 +- ...ide_automatically_added_default_trait.snap | 6 +- .../structs/snapshots/recursive_struct.snap | 4 +- .../simple_generic_tuple_struct.snap | 4 +- .../structs/snapshots/simple_generics.snap | 4 +- .../structs/snapshots/simple_struct.snap | 4 +- .../simple_struct_with_custom_crate.snap | 4 +- .../src/internals/deserialize/unions/mod.rs | 5 +- .../src/internals/enum_discriminant.rs | 12 +- borsh-derive/src/internals/generics.rs | 24 +- .../src/internals/schema/enums/mod.rs | 169 ++++---- borsh-derive/src/internals/schema/mod.rs | 15 +- .../src/internals/schema/structs/mod.rs | 218 +++++----- .../src/internals/serialize/enums/mod.rs | 215 +++++----- .../snapshots/borsh_discriminant_false.snap | 4 +- .../snapshots/borsh_discriminant_true.snap | 4 +- .../borsh_skip_struct_variant_all_fields.snap | 4 +- .../borsh_skip_struct_variant_field.snap | 4 +- .../borsh_skip_tuple_variant_field.snap | 4 +- .../enums/snapshots/bound_generics.snap | 4 +- .../snapshots/check_serialize_with_attr.snap | 4 +- .../generic_borsh_skip_struct_field.snap | 4 +- .../generic_borsh_skip_tuple_field.snap | 4 +- .../snapshots/generic_serialize_bound.snap | 4 +- .../snapshots/mixed_with_unit_variants.snap | 4 +- .../enums/snapshots/recursive_enum.snap | 4 +- .../simple_enum_with_custom_crate.snap | 4 +- .../enums/snapshots/simple_generics.snap | 4 +- .../enums/snapshots/struct_variant_field.snap | 4 +- borsh-derive/src/internals/serialize/mod.rs | 33 +- .../src/internals/serialize/structs/mod.rs | 184 +++++---- .../structs/snapshots/bound_generics.snap | 4 +- .../snapshots/check_serialize_with_attr.snap | 4 +- .../check_serialize_with_skip_conflict.snap | 2 +- .../snapshots/generic_associated_type.snap | 4 +- ...eneric_named_fields_struct_borsh_skip.snap | 4 +- .../snapshots/generic_serialize_bound.snap | 4 +- .../generic_tuple_struct_borsh_skip1.snap | 4 +- .../generic_tuple_struct_borsh_skip2.snap | 4 +- ..._generic_associated_type_wrong_derive.snap | 4 +- .../structs/snapshots/recursive_struct.snap | 4 +- .../simple_generic_tuple_struct.snap | 4 +- .../structs/snapshots/simple_generics.snap | 4 +- .../structs/snapshots/simple_struct.snap | 4 +- .../simple_struct_with_custom_crate.snap | 4 +- .../src/internals/serialize/unions/mod.rs | 5 +- borsh-derive/src/internals/test_helpers.rs | 34 +- borsh-derive/src/lib.rs | 44 +- 89 files changed, 2005 insertions(+), 1021 deletions(-) create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics-2.snap 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..98e4824be 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 ), )); } @@ -176,6 +231,15 @@ 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() @@ -191,7 +255,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 +265,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 +303,31 @@ impl Attributes { #[cfg(test)] mod tests { - use quote::quote; - use syn::{Attribute, ItemStruct}; + use syn::{parse_quote, Attribute, ItemStruct}; - fn parse_bounds(attrs: &[Attribute]) -> Result, syn::Error> { - // #[borsh(bound(serialize = "...", deserialize = "..."))] + 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(borsh_attrs.bounds) + Ok(ParsedBounds { + common: borsh_attrs.bounds, + r#async: borsh_attrs.async_bounds, + }) } + 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}; - #[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 +338,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 +350,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 +360,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 +380,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 +399,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 +443,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 +461,142 @@ 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))] + #[borsh(async_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::BorshDeserialize, + V: borsh::de::BorshDeserialize", + serialize = "K: Hash + Eq + borsh::ser::BorshSerialize, + V: borsh::ser::BorshSerialize" + ))] + 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::BorshDeserialize, + V: borsh::de::BorshDeserialize", + 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 +608,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,8 +617,7 @@ 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(); @@ -436,14 +626,13 @@ mod tests { } #[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]; @@ -452,13 +641,12 @@ mod tests { } #[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 +658,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::{ @@ -477,11 +668,6 @@ mod tests_schema { local_insta_assert_debug_snapshot, local_insta_assert_snapshot, }, }; - - 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 +676,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 +686,7 @@ mod tests_schema { x: u64, y: String, } - }) - .unwrap(); + }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; @@ -511,13 +696,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,8 +713,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(); @@ -537,7 +721,7 @@ mod tests_schema { } #[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 +732,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 +744,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 +755,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 +767,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,8 +778,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(); @@ -605,7 +786,7 @@ mod tests_schema { } #[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 +795,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 +804,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 +812,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 +821,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 +830,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 +852,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 +866,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 +884,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 +892,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/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..20d708a96 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::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{Fields, ItemEnum, Path, 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(); }); + generics_output.extend::(&mut where_clause, &cratename); + + let deserialize_trait = if IS_ASYNC { + quote! { BorshDeserializeAsync } + } else { + quote! { BorshDeserialize } + }; + let enum_ext = if IS_ASYNC { + quote! { EnumExtAsync } } else { - quote! {} + quote! { EnumExt } }; - generics_output.extend(&mut where_clause, &cratename); + let read_trait_path = if IS_ASYNC { + quote! { async_io::AsyncRead } + } else { + quote! { io::Read } + }; + let async_trait = IS_ASYNC.then(|| quote! { #[::async_trait::async_trait] }); + let r#async = IS_ASYNC.then(|| syn::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) + #async_trait + 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>( + #async_trait + 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 = #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 = 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_enum.clone(), crate_.clone()).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_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, @@ -173,16 +205,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 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,18 @@ mod tests { }, D(u32, u32), } - }) - .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 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 +305,18 @@ mod tests { y: ThirdParty }, } - }) - .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 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 +326,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, @@ -305,15 +346,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_init_func() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { #[borsh(init = initialization_method)] enum A { A, @@ -323,9 +366,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..1c9faef60 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_false-2.snap @@ -0,0 +1,45 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut 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..6ceab9cb0 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>( @@ -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..98bd8cfdb --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_discriminant_true-2.snap @@ -0,0 +1,45 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut 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..e62028c67 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>( @@ -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..89943b024 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_init_func-2.snap @@ -0,0 +1,46 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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..6b54de688 --- /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() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + AA::B { + c: ::core::default::Default::default(), + d: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + } + } else if variant_tag == 1u8 { + AA::NegatedVariant { + beta: 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/borsh_skip_struct_variant_field.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_struct_variant_field.snap index a8a2d9e1a..040c9bf70 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>( @@ -17,7 +17,7 @@ impl borsh::de::EnumExt for AA { ) -> ::core::result::Result { let mut return_value = if variant_tag == 0u8 { AA::B { - c: core::default::Default::default(), + c: ::core::default::Default::default(), d: borsh::BorshDeserialize::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { @@ -25,7 +25,7 @@ impl borsh::de::EnumExt for AA { beta: 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!( @@ -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..5e2b62fee --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap @@ -0,0 +1,42 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + AAT::B( + ::core::default::Default::default(), + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ) + } else if variant_tag == 1u8 { + AAT::NegatedVariant { + beta: 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/borsh_skip_tuple_variant_field.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/borsh_skip_tuple_variant_field.snap index 60149fc60..ce2969dc8 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>( @@ -17,7 +17,7 @@ impl borsh::de::EnumExt for AAT { ) -> ::core::result::Result { let mut return_value = if variant_tag == 0u8 { AAT::B( - core::default::Default::default(), + ::core::default::Default::default(), borsh::BorshDeserialize::deserialize_reader(reader)?, ) } else if variant_tag == 1u8 { @@ -25,7 +25,7 @@ impl borsh::de::EnumExt for AAT { beta: 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!( @@ -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..1d20e873c --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics-2.snap @@ -0,0 +1,55 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + A::B { + x: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + } + } else if variant_tag == 1u8 { + A::C( + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + 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..5cc05304f 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 @@ -38,7 +38,7 @@ where 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 +47,6 @@ where ), ) }; - Ok(return_value) + ::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..a96e5e3d6 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_attr-2.snap @@ -0,0 +1,51 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + C::C3( + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ) + } else if variant_tag == 1u8 { + C::C4 { + x: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + y: 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..495349816 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 @@ -34,7 +34,7 @@ where 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..4447960e0 --- /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() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + A::B { + x: ::core::default::Default::default(), + y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + } + } else if variant_tag == 1u8 { + A::C( + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + 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..a28dd1d24 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,8 +22,8 @@ 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, @@ -31,7 +31,7 @@ where ) -> ::core::result::Result { let mut return_value = if variant_tag == 0u8 { A::B { - x: core::default::Default::default(), + x: ::core::default::Default::default(), y: borsh::BorshDeserialize::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { @@ -40,7 +40,7 @@ where 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..a75f18467 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap @@ -0,0 +1,55 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + A::B { + x: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + } + } else if variant_tag == 1u8 { + A::C( + borsh::BorshDeserializeAsync::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..2a1711d79 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,7 +21,7 @@ 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, @@ -35,10 +35,10 @@ where } else if variant_tag == 1u8 { A::C( borsh::BorshDeserialize::deserialize_reader(reader)?, - core::default::Default::default(), + ::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 +47,6 @@ where ), ) }; - Ok(return_value) + ::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..42989fee7 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound-2.snap @@ -0,0 +1,51 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +impl borsh::de::BorshDeserializeAsync for A +where + T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize, + U: borsh::de::BorshDeserialize, +{ + 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 + } +} +#[::async_trait::async_trait] +impl borsh::de::EnumExtAsync for A +where + T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize, + U: borsh::de::BorshDeserialize, +{ + 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::C { + a: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + b: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + } + } else if variant_tag == 1u8 { + A::D( + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + 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_deserialize_bound.snap b/borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_bound.snap index adf641118..36f3667dd 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 @@ -34,7 +34,7 @@ where 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!( @@ -43,6 +43,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..ce04d99b9 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum-2.snap @@ -0,0 +1,53 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + A::B { + x: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + } + } else if variant_tag == 1u8 { + A::C( + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + 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..5ccc804be 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 @@ -36,7 +36,7 @@ where 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 +45,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..2c0a88011 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_enum_with_custom_crate-2.snap @@ -0,0 +1,50 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + A::B { + x: reexporter::borsh::BorshDeserializeAsync::deserialize_reader(reader) + .await?, + y: reexporter::borsh::BorshDeserializeAsync::deserialize_reader(reader) + .await?, + } + } else if variant_tag == 1u8 { + A::C( + reexporter::borsh::BorshDeserializeAsync::deserialize_reader(reader) + .await?, + 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..36de9b1d5 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>( @@ -28,7 +28,7 @@ impl reexporter::borsh::de::EnumExt for A { 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 +37,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..1ec3afbc0 --- /dev/null +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics-2.snap @@ -0,0 +1,53 @@ +--- +source: borsh-derive/src/internals/deserialize/enums/mod.rs +expression: pretty_print_syn_str(actual).unwrap() +--- +#[::async_trait::async_trait] +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 + } +} +#[::async_trait::async_trait] +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 mut return_value = if variant_tag == 0u8 { + A::B { + x: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + } + } else if variant_tag == 1u8 { + A::C( + borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + 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..2ea9415ea 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 @@ -36,7 +36,7 @@ where 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 +45,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..07327a086 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}; use super::{ attributes::{field, BoundType}, @@ -25,9 +25,13 @@ 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 +42,7 @@ impl GenericsOutput { } } -fn process_field( +fn process_field( field: &syn::Field, cratename: &Path, body: &mut TokenStream2, @@ -61,7 +65,15 @@ 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, + cratename, + if IS_ASYNC { + parsed.deserialize_with_async + } else { + parsed.deserialize_with + }, + ) }; body.extend(delta); Ok(()) @@ -69,22 +81,26 @@ 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>, 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); - if let Some(field_name) = field_name { - quote! { - #field_name: #path(reader)?, + let default_path = || { + if IS_ASYNC { + parse_quote! { #cratename::BorshDeserializeAsync::deserialize_reader } + } else { + parse_quote! { #cratename::BorshDeserialize::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)#dot_await?, } } else { - quote! { - #path(reader)?, - } + quote! { #path(reader)#dot_await?, } } } @@ -92,10 +108,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..1d61b7533 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::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{Fields, ItemStruct, Path}; 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,7 +18,12 @@ 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)?; + deserialize::process_field::( + field, + &cratename, + &mut body, + &mut generics_output, + )?; } quote! { Self { #body } @@ -23,7 +31,12 @@ pub fn process(input: &ItemStruct, cratename: Path) -> syn::Result } Fields::Unnamed(fields) => { for field in fields.unnamed.iter() { - deserialize::process_field(field, &cratename, &mut body, &mut generics_output)?; + deserialize::process_field::( + field, + &cratename, + &mut body, + &mut generics_output, + )?; } quote! { Self( #body ) @@ -35,173 +48,177 @@ pub fn process(input: &ItemStruct, cratename: Path) -> syn::Result } } }; - 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 = if IS_ASYNC { + quote! { BorshDeserializeAsync } + } else { + quote! { BorshDeserialize } + }; + 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 async_trait = IS_ASYNC.then(|| quote! { #[::async_trait::async_trait] }); + let r#async = IS_ASYNC.then(|| syn::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! { + #async_trait + 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, 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_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 }; + let actual = process::(item_struct, crate_).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).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 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, 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, 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, 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_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_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 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 +227,52 @@ mod tests { ))] 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 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, 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 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, 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_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, 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.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func.snap index 61f51e48e..8ddc9e728 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,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 { fn deserialize_reader<__R: borsh::io::Read>( @@ -11,6 +11,6 @@ impl borsh::de::BorshDeserialize for A { y: borsh::BorshDeserialize::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.snap b/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics.snap index dc4514d64..232936337 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,7 +11,7 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { + ::core::result::Result::Ok(Self { x: borsh::BorshDeserialize::deserialize_reader(reader)?, y: borsh::BorshDeserialize::deserialize_reader(reader)?, }) 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..25e053721 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,7 +10,7 @@ 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)?, }) 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..dc7c2ce92 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,7 +10,7 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { + ::core::result::Result::Ok(Self { a: borsh::BorshDeserialize::deserialize_reader(reader)?, b: borsh::BorshDeserialize::deserialize_reader(reader)?, }) 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..17e3635c6 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,18 +1,18 @@ --- 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(), + ::core::result::Result::Ok(Self { + x: ::core::default::Default::default(), y: borsh::BorshDeserialize::deserialize_reader(reader)?, }) } 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..dcacef19b 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,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( + ::core::result::Result::Ok( Self( - core::default::Default::default(), + ::core::default::Default::default(), borsh::BorshDeserialize::deserialize_reader(reader)?, ), ) 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..823d05e41 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(), + ::core::default::Default::default(), ), ) } 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..c8556e104 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,9 +9,9 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok( + ::core::result::Result::Ok( Self( - core::default::Default::default(), + ::core::default::Default::default(), borsh::BorshDeserialize::deserialize_reader(reader)?, ), ) 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..b2ea3a66f 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap @@ -1,12 +1,12 @@ --- 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 { + ::core::result::Result::Ok(Self { a: borsh::BorshDeserialize::deserialize_reader(reader)?, b: borsh::BorshDeserialize::deserialize_reader(reader)?, }) 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..48b801d82 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,7 +9,7 @@ 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)?, 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..e73fa05df 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,7 +10,7 @@ where fn deserialize_reader<__R: borsh::io::Read>( reader: &mut __R, ) -> ::core::result::Result { - Ok(Self { + ::core::result::Result::Ok(Self { x: borsh::BorshDeserialize::deserialize_reader(reader)?, y: borsh::BorshDeserialize::deserialize_reader(reader)?, }) 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..367c83c1c 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap @@ -1,12 +1,12 @@ --- 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 { + ::core::result::Result::Ok(Self { x: borsh::BorshDeserialize::deserialize_reader(reader)?, y: borsh::BorshDeserialize::deserialize_reader(reader)?, }) 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..e85cdfed5 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,12 +1,12 @@ --- 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 { + ::core::result::Result::Ok(Self { x: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, y: reexporter::borsh::BorshDeserialize::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..40a760b28 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}; @@ -14,7 +14,7 @@ fn field_declaration_output( declaration_override: Option, ) -> TokenStream2 { let default_path: ExprPath = - syn::parse2(quote! { <#field_type as #cratename::BorshSchema>::declaration }).unwrap(); + parse_quote! { <#field_type as #cratename::BorshSchema>::declaration }; let path = declaration_override.unwrap_or(default_path); @@ -48,10 +48,10 @@ fn field_definitions_output( } } -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); @@ -162,103 +162,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 +260,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 +382,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 +402,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 +422,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 +442,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 +460,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 +478,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 +497,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..895ea8567 100644 --- a/borsh-derive/src/internals/serialize/enums/mod.rs +++ b/borsh-derive/src/internals/serialize/enums/mod.rs @@ -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,41 @@ 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 = if IS_ASYNC { + quote!(BorshSerializeAsync) + } else { + quote!(BorshSerialize) + }; + let writer_trait = if IS_ASYNC { + quote!(async_io::AsyncWrite) + } else { + quote!(io::Write) + }; + let async_trait = if IS_ASYNC { + quote! { #[::async_trait::async_trait] } + } else { + quote!() + }; + let r#async = if IS_ASYNC { quote!(async) } else { quote!() }; + let dot_await = if IS_ASYNC { + quote! { .await } + } else { + quote!() + }; 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> { + #async_trait + impl #impl_generics #cratename::ser::#serialize_trait for #enum_ident #ty_generics #where_clause { + #r#async fn serialize<__W: #cratename::#writer_trait>(&self, writer: &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())?; + writer.write_all(&variant_idx.to_le_bytes())#dot_await?; #fields_body - Ok(()) + ::core::result::Result::Ok(()) } } }) @@ -123,7 +149,7 @@ struct VariantOutput { variant_idx_body: TokenStream2, } -fn process_variant( +fn process_variant( variant: &Variant, enum_ident: &Ident, discriminant_value: &TokenStream2, @@ -136,7 +162,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 +181,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 +206,7 @@ fn process_variant( Ok(variant_output) } -fn process_field( +fn process_field( field: &syn::Field, field_id: serialize::FieldId, cratename: &Path, @@ -188,7 +226,14 @@ fn process_field( } if !parsed.skip { - let delta = field_id.serialize_output(cratename, parsed.serialize_with); + let delta = field_id.serialize_output::( + 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 +244,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 +260,15 @@ mod tests { beta: u8, } } - }) - .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 struct_variant_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AB { B { c: i32, @@ -234,17 +279,16 @@ mod tests { beta: String, } } - }) - .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 AB { B { c: i32, @@ -255,18 +299,17 @@ mod tests { beta: String, } } - }) - .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_skip_struct_variant_field() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AB { B { @@ -280,17 +323,16 @@ mod tests { beta: String, } } - }) - .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_skip_struct_variant_all_fields() { - let item_enum: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum AAB { B { @@ -305,17 +347,16 @@ mod tests { beta: String, } } - }) - .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_generics() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { B { x: HashMap, @@ -323,16 +364,15 @@ 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, 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 +380,15 @@ 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, 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 +396,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_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 +414,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_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 +431,16 @@ mod tests { }, C(K, #[borsh(skip)] 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_serialize_bound() { - let item_struct: ItemEnum = syn::parse2(quote! { + let item_enum: ItemEnum = parse_quote! { enum A { C { a: String, @@ -416,17 +452,16 @@ mod tests { }, D(u32, u32), } - }) - .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 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 +470,16 @@ mod tests { y: 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()); } #[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 +489,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, @@ -473,26 +506,24 @@ 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 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, 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/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.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.snap b/borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields.snap index b8943a467..51f0d5c37 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>( @@ -18,6 +18,6 @@ impl borsh::ser::BorshSerialize for AAB { borsh::BorshSerialize::serialize(beta, writer)?; } } - Ok(()) + ::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..af35f501a 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>( @@ -20,6 +20,6 @@ impl borsh::ser::BorshSerialize for AB { borsh::BorshSerialize::serialize(beta, writer)?; } } - Ok(()) + ::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..202707f5b 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>( @@ -18,6 +18,6 @@ impl borsh::ser::BorshSerialize for AATTB { borsh::BorshSerialize::serialize(beta, writer)?; } } - Ok(()) + ::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..76c134aa7 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 @@ -28,6 +28,6 @@ where borsh::BorshSerialize::serialize(id1, writer)?; } } - Ok(()) + ::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..4f1582a8c 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 @@ -26,6 +26,6 @@ where 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.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field.snap index 051033a64..244488064 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 @@ -26,6 +26,6 @@ where 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.snap b/borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field.snap index 4f0ae41b7..ac1f1c6fc 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 @@ -26,6 +26,6 @@ where borsh::BorshSerialize::serialize(id0, writer)?; } } - Ok(()) + ::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..54fff0c5e 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 @@ -26,6 +26,6 @@ where borsh::BorshSerialize::serialize(id1, writer)?; } } - Ok(()) + ::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..b1295d8b1 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>( @@ -24,6 +24,6 @@ impl borsh::ser::BorshSerialize for X { } _ => {} } - Ok(()) + ::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..320d2a29f 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 @@ -27,6 +27,6 @@ where 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.snap b/borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate.snap index fcfc55df6..20fe3f9b0 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>( @@ -21,6 +21,6 @@ impl reexporter::borsh::ser::BorshSerialize for AB { reexporter::borsh::BorshSerialize::serialize(beta, writer)?; } } - Ok(()) + ::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..a7073cbf7 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 @@ -27,6 +27,6 @@ where borsh::BorshSerialize::serialize(id1, writer)?; } } - Ok(()) + ::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..44998ce45 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>( @@ -21,6 +21,6 @@ impl borsh::ser::BorshSerialize for AB { borsh::BorshSerialize::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..cc942ad5e 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}; 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,27 +70,33 @@ 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, cratename: &Path, serialize_with: Option, ) -> TokenStream2 { let arg: Expr = self.serialize_arg(); + let dot_await = IS_ASYNC.then_some(quote! { .await }); + let serialize_trait = if IS_ASYNC { + quote! { BorshSerializeAsync } + } else { + quote! { BorshSerialize } + }; if let Some(func) = serialize_with { - quote! { #func(#arg, writer)?; } + quote! { #func(#arg, writer)#dot_await?; } } else { - quote! { #cratename::BorshSerialize::serialize(#arg, writer)?; } + quote! { #cratename::#serialize_trait::serialize(#arg, writer)#dot_await?; } } } pub fn enum_variant_header(&self, skipped: bool) -> Option { diff --git a/borsh-derive/src/internals/serialize/structs/mod.rs b/borsh-derive/src/internals/serialize/structs/mod.rs index 2864c78e9..ed5790d2d 100644 --- a/borsh-derive/src/internals/serialize/structs/mod.rs +++ b/borsh-derive/src/internals/serialize/structs/mod.rs @@ -7,9 +7,12 @@ use crate::internals::{ 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,54 @@ 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 = if IS_ASYNC { + quote! { BorshSerializeAsync } + } else { + quote! { BorshSerialize } + }; + let writer_trait_path = if IS_ASYNC { + quote! { async_io::AsyncWrite } + } else { + quote! { io::Write } + }; 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 { + fn serialize<__W: #cratename::#writer_trait_path>(&self, writer: &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, @@ -57,7 +83,14 @@ fn process_field( .overrides .extend(parsed.collect_bounds(BoundType::Serialize)); if !parsed.skip { - let delta = field_id.serialize_output(cratename, parsed.serialize_with); + let delta = field_id.serialize_output::( + cratename, + if IS_ASYNC { + parsed.serialize_with_async + } else { + parsed.serialize_with + }, + ); body.extend(delta); if needs_bounds_derive { @@ -69,149 +102,141 @@ 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, 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_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 }; + let actual = process::(item_struct, crate_).unwrap(); - local_insta_assert_snapshot!(pretty_print_syn_str(&actual).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 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, 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, 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, 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_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_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 generic_associated_type() { - let item_struct: ItemStruct = syn::parse2(quote! { + let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName, @@ -219,17 +244,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 +262,16 @@ mod tests { ))] 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 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 +279,39 @@ 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 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, 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 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")] x: ThirdParty, y: u64, } - }) - .unwrap(); + }; - 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/bound_generics.snap b/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics.snap index 5c7c6926b..2b980a463 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 @@ -14,6 +14,6 @@ where ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.x, writer)?; borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::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..19182d8bb 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 @@ -13,6 +13,6 @@ where ) -> ::core::result::Result<(), borsh::io::Error> { third_party_impl::serialize_third_party(&self.x, writer)?; borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::core::result::Result::Ok(()) } } 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..518aa61a7 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 @@ -14,6 +14,6 @@ where ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.field, writer)?; borsh::BorshSerialize::serialize(&self.another, writer)?; - Ok(()) + ::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..fc41a7cfc 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 @@ -11,6 +11,6 @@ where writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::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..112bd5cd2 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 @@ -13,6 +13,6 @@ where ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.a, writer)?; borsh::BorshSerialize::serialize(&self.b, writer)?; - Ok(()) + ::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..852a4e452 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 @@ -11,6 +11,6 @@ where writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.1, writer)?; - Ok(()) + ::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..ab4dc9312 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 @@ -12,6 +12,6 @@ where writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.0, writer)?; - Ok(()) + ::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..7de5e9c97 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 @@ -14,6 +14,6 @@ where ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.field, writer)?; borsh::BorshSerialize::serialize(&self.another, writer)?; - Ok(()) + ::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..beb4a1f5c 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/recursive_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 CRecC { fn serialize<__W: borsh::io::Write>( @@ -9,6 +9,6 @@ impl borsh::ser::BorshSerialize for CRecC { ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.a, writer)?; borsh::BorshSerialize::serialize(&self.b, writer)?; - Ok(()) + ::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..f7cfd69d2 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 @@ -12,6 +12,6 @@ where ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.0, writer)?; borsh::BorshSerialize::serialize(&self.1, writer)?; - Ok(()) + ::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..12c26f9e9 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 @@ -13,6 +13,6 @@ where ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.x, writer)?; borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::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..dd36b7e50 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_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 A { fn serialize<__W: borsh::io::Write>( @@ -9,6 +9,6 @@ impl borsh::ser::BorshSerialize for A { ) -> ::core::result::Result<(), borsh::io::Error> { borsh::BorshSerialize::serialize(&self.x, writer)?; borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::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..6e84fd5da 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,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 reexporter::borsh::ser::BorshSerialize for A { fn serialize<__W: reexporter::borsh::io::Write>( @@ -9,6 +9,6 @@ impl reexporter::borsh::ser::BorshSerialize for A { ) -> ::core::result::Result<(), reexporter::borsh::io::Error> { reexporter::borsh::BorshSerialize::serialize(&self.x, writer)?; reexporter::borsh::BorshSerialize::serialize(&self.y, writer)?; - Ok(()) + ::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(), From d64ff6b7fcde29833fc14af0a803b4a203e48157 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 21:23:34 +0200 Subject: [PATCH 33/69] Rename async-related features --- borsh/Cargo.toml | 6 +-- borsh/src/async_io.rs | 9 ++-- borsh/src/de/mod.rs | 98 ++++++++++++++++++------------------- borsh/src/error.rs | 1 + borsh/src/lib.rs | 10 ++-- borsh/src/ser/helpers.rs | 4 +- borsh/src/ser/mod.rs | 102 +++++++++++++++++++-------------------- 7 files changed, 115 insertions(+), 115 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 3ccaeedb0..4e9353746 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -57,9 +57,9 @@ targets = ["x86_64-unknown-linux-gnu"] [features] default = ["std"] derive = ["borsh-derive"] -async = [] -tokio = ["async", "dep:tokio"] -async-std = ["async", "dep:async-std"] +unstable__async = [] +unstable__tokio = ["unstable__async", "dep:tokio", "std"] +unstable__async-std = ["unstable__async", "dep:async-std", "std"] unstable__schema = ["derive", "borsh-derive/schema"] std = [] # Opt into impls for Rc and Arc. Serializing and deserializing these types diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index c51d6348d..a793941a2 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -108,8 +108,7 @@ pub trait AsyncRead: Unpin + Send { } } -#[cfg(feature = "tokio")] -// #[async_trait] +#[cfg(feature = "unstable__tokio")] impl AsyncRead for R { #[inline] fn read<'a>( @@ -187,7 +186,7 @@ impl AsyncRead for R { } } -#[cfg(feature = "async-std")] +#[cfg(feature = "unstable__async-std")] impl AsyncRead for R { #[inline] fn read<'a>( @@ -306,7 +305,7 @@ pub trait AsyncWrite: Unpin + Send { } } -#[cfg(feature = "tokio")] +#[cfg(feature = "unstable__tokio")] impl AsyncWrite for R { #[inline] fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { @@ -374,7 +373,7 @@ impl AsyncWrite for R { } } -#[cfg(feature = "async-std")] +#[cfg(feature = "unstable__async-std")] impl AsyncWrite for R { #[inline] fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index de4e71851..eaed26a65 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] use core::future::Future; use core::{ convert::{TryFrom, TryInto}, @@ -10,7 +10,7 @@ use async_generic::async_generic; #[cfg(feature = "bytes")] use bytes::{BufMut, BytesMut}; -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] use crate::async_io::AsyncRead; use crate::{ __private::maybestd::{ @@ -84,7 +84,7 @@ pub trait BorshDeserialize: Sized { } /// A data-structure that can be asynchronously de-serialized from binary format by NBOR. -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] pub trait BorshDeserializeAsync: Sized + Send { fn deserialize_reader( reader: &mut R, @@ -184,7 +184,7 @@ pub trait EnumExt: BorshDeserialize { } /// Additional methods offered on enums which is used by `[derive(BorshDeserializeAsync)]`. -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] pub trait EnumExtAsync: BorshDeserializeAsync { /// Deserialises given variant of an enum from the async reader. /// @@ -256,7 +256,7 @@ fn unexpected_eof_to_unexpected_length_of_input(e: Error) -> Error { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for u8 { @@ -330,7 +330,7 @@ impl BorshDeserialize for u8 { macro_rules! impl_for_integer { ($type: ident, $method: ident) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for $type { @@ -368,7 +368,7 @@ impl_for_integer!(u128, read_u128); macro_rules! impl_for_nonzero_integer { ($type: ty, $repr: ty) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for $type { @@ -403,7 +403,7 @@ impl_for_nonzero_integer!(core::num::NonZeroUsize, usize); macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for $type { @@ -431,7 +431,7 @@ impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); macro_rules! impl_for_float { ($type: ident, $int_type: ident, $method: ident) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for $type { @@ -463,7 +463,7 @@ impl_for_float!(f32, u32, read_f32); impl_for_float!(f64, u64, read_f64); #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for bool { @@ -487,7 +487,7 @@ impl BorshDeserialize for bool { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -522,7 +522,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -562,7 +562,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for String { @@ -593,13 +593,13 @@ impl BorshDeserialize for String { pub mod ascii { //! //! Module defines [`BorshDeserialize`] - #![cfg_attr(feature = "async", doc = " & [`BorshDeserializeAsync`]")] + #![cfg_attr(feature = "unstable__async", doc = " & [`BorshDeserializeAsync`]")] //! implementation for some types from [`ascii`] crate. use async_generic::async_generic; use super::BorshDeserialize; - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use super::{AsyncRead, BorshDeserializeAsync}; use crate::{ __private::maybestd::vec::Vec, @@ -607,7 +607,7 @@ pub mod ascii { }; #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for ascii::AsciiString { @@ -634,7 +634,7 @@ pub mod ascii { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for ascii::AsciiChar { @@ -662,7 +662,7 @@ pub mod ascii { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -704,7 +704,7 @@ where #[cfg(feature = "bytes")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for bytes::Bytes { @@ -722,7 +722,7 @@ impl BorshDeserialize for bytes::Bytes { #[cfg(feature = "bytes")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for BytesMut { @@ -748,7 +748,7 @@ impl BorshDeserialize for BytesMut { #[cfg(feature = "bson")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for bson::oid::ObjectId { @@ -765,7 +765,7 @@ impl BorshDeserialize for bson::oid::ObjectId { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: ToOwned + ?Sized, @@ -788,7 +788,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -809,7 +809,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -832,7 +832,7 @@ where /// Module is available if borsh is built with `features = ["std"]` or `features = ["hashbrown"]`. /// /// Module defines [`BorshDeserialize`] -#[cfg_attr(feature = "async", doc = " & [`BorshDeserializeAsync`]")] +#[cfg_attr(feature = "unstable__async", doc = " & [`BorshDeserializeAsync`]")] /// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { @@ -841,7 +841,7 @@ pub mod hashes { use async_generic::async_generic; use super::BorshDeserialize; - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use super::{AsyncRead, BorshDeserializeAsync}; #[cfg(feature = "de_strict_order")] use crate::io::{Error, ErrorKind}; @@ -858,7 +858,7 @@ pub mod hashes { const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order"; #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync + Eq + Hash + Ord, @@ -902,7 +902,7 @@ pub mod hashes { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where K: BorshDeserializeAsync + Eq + Hash + Ord, @@ -950,7 +950,7 @@ pub mod hashes { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync + Ord, @@ -993,7 +993,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where K: BorshDeserializeAsync + Ord, @@ -1041,7 +1041,7 @@ where #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for std::net::SocketAddr { @@ -1076,7 +1076,7 @@ impl BorshDeserialize for std::net::SocketAddr { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for std::net::IpAddr { @@ -1111,7 +1111,7 @@ impl BorshDeserialize for std::net::IpAddr { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for std::net::SocketAddrV4 { @@ -1134,7 +1134,7 @@ impl BorshDeserialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for std::net::SocketAddrV6 { @@ -1157,7 +1157,7 @@ impl BorshDeserialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for std::net::Ipv4Addr { @@ -1174,7 +1174,7 @@ impl BorshDeserialize for std::net::Ipv4Addr { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for std::net::Ipv6Addr { @@ -1190,7 +1190,7 @@ impl BorshDeserialize for std::net::Ipv6Addr { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where U: Into> + Borrow, @@ -1271,7 +1271,7 @@ where } } -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] impl BorshDeserializeAsync for [T; N] where T: BorshDeserializeAsync, @@ -1346,7 +1346,7 @@ fn array_deserialization_doesnt_leak() { struct MyType(u8); #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for MyType { @@ -1393,7 +1393,7 @@ fn array_deserialization_doesnt_leak() { macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for $name { @@ -1409,7 +1409,7 @@ macro_rules! impl_tuple { ($($name:ident)+) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant<$($name),+> where $($name: BorshDeserializeAsync,)+ @@ -1458,7 +1458,7 @@ impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T1 macro_rules! impl_range { ($type:ident, $make:expr, $n: literal, $($side:ident),*) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -1488,13 +1488,13 @@ impl_range!(RangeToInclusive, ..=end, 1, end); pub mod rc { //! //! Module defines [`BorshDeserialize`] - #![cfg_attr(feature = "async", doc = " & [`BorshDeserializeAsync`]")] + #![cfg_attr(feature = "unstable__async", doc = " & [`BorshDeserializeAsync`]")] //! implementation for [`alloc::rc::Rc`](Rc) and [`alloc::sync::Arc`](Arc). use async_generic::async_generic; use super::BorshDeserialize; - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use super::{AsyncRead, BorshDeserializeAsync}; use crate::{ __private::maybestd::{boxed::Box, rc::Rc, sync::Arc}, @@ -1522,7 +1522,7 @@ pub mod rc { /// deduplicate `Arc` references to the same data. Every deserialized `Arc` /// will end up with a strong count of 1. #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where Box: BorshDeserializeAsync, @@ -1544,7 +1544,7 @@ pub mod rc { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshDeserialize for PhantomData { @@ -1558,7 +1558,7 @@ impl BorshDeserialize for PhantomData { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -1576,7 +1576,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshDeserializeAsync, @@ -1653,7 +1653,7 @@ pub fn from_slice(v: &[u8]) -> Result { /// assert_eq!(original, decoded); /// ``` #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_signature[impl_fut]<'a, R: AsyncRead, T: BorshDeserializeAsync + 'a>(reader: &'a mut R) -> impl Future> + Send + 'a )] pub fn from_reader(reader: &mut R) -> Result { diff --git a/borsh/src/error.rs b/borsh/src/error.rs index 623c70564..615ff6edc 100644 --- a/borsh/src/error.rs +++ b/borsh/src/error.rs @@ -1,6 +1,7 @@ use core::mem::size_of; use crate::io::{Error, ErrorKind, Result}; + pub const ERROR_ZST_FORBIDDEN: &str = "Collections of zero-sized types are not allowed due to deny-of-service concerns on deserialization."; pub(crate) fn check_zst() -> Result<()> { diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index ca0fca5c0..6fa67e008 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -25,7 +25,7 @@ pub(crate) mod schema_helpers; pub mod ser; pub use de::{from_reader, from_slice, BorshDeserialize}; -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] pub use de::{from_reader_async, BorshDeserializeAsync}; #[cfg(feature = "unstable__schema")] pub use schema::BorshSchema; @@ -33,7 +33,7 @@ pub use schema::BorshSchema; pub use schema_helpers::{ max_serialized_size, schema_container_of, try_from_slice_with_schema, try_to_vec_with_schema, }; -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] pub use ser::{helpers::to_writer_async, BorshSerializeAsync}; pub use ser::{ helpers::{object_length, to_vec, to_writer}, @@ -44,12 +44,12 @@ pub mod error; #[cfg(all(feature = "std", feature = "hashbrown"))] compile_error!("feature \"std\" and feature \"hashbrown\" don't make sense at the same time"); -#[cfg(all(feature = "tokio", feature = "async-std"))] -compile_error!("Cannot enable both `async-tokio` and `async-std` features at the same time"); +#[cfg(all(feature = "unstable__tokio", feature = "unstable__async-std"))] +compile_error!("Cannot enable both `unstable__tokio` and `unstable__async-std` features at the same time"); #[cfg(feature = "std")] use std::io as io_impl; -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] pub mod async_io; #[cfg(not(feature = "std"))] mod nostd_io; diff --git a/borsh/src/ser/helpers.rs b/borsh/src/ser/helpers.rs index 6f9061cb8..58ed90d32 100644 --- a/borsh/src/ser/helpers.rs +++ b/borsh/src/ser/helpers.rs @@ -1,6 +1,6 @@ use async_generic::async_generic; -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] use crate::{async_io::AsyncWrite, BorshSerializeAsync}; use crate::{ BorshSerialize, @@ -36,7 +36,7 @@ where /// assert_eq!((), borsh::to_writer(&stderr, "hello_0x0a").unwrap()); /// ``` sync_signature; - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_signature(mut writer: W, value: &T) -> Result<()> where T: BorshSerializeAsync + ?Sized, diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 9af651615..959156048 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -1,10 +1,10 @@ -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] use core::future::Future; use core::{convert::TryFrom, marker::PhantomData}; use async_generic::async_generic; -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] use crate::async_io::AsyncWrite; use crate::{ __private::maybestd::{ @@ -102,7 +102,7 @@ pub trait BorshSerialize { /// x.serialize(&mut buffer_slice_enough_for_the_data).unwrap(); /// # }) /// ``` -#[cfg(feature = "async")] +#[cfg(feature = "unstable__async")] pub trait BorshSerializeAsync: Sync { fn serialize<'a, W: AsyncWrite>( &'a self, @@ -121,7 +121,7 @@ pub trait BorshSerializeAsync: Sync { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant(copy_sync) )] impl BorshSerialize for u8 { @@ -146,7 +146,7 @@ impl BorshSerialize for u8 { macro_rules! impl_for_integer { ($type: ident, $method: ident) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for $type { @@ -179,7 +179,7 @@ impl_for_integer!(u128, write_u128); macro_rules! impl_for_nonzero_integer { ($type: ty, $method: ident $(, $repr: ty)?) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for $type { @@ -215,7 +215,7 @@ impl_for_nonzero_integer!(core::num::NonZeroUsize, write_u64, u64); macro_rules! impl_for_size_integer { ($type:ty: $repr:ty, $method: ident) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for $type { @@ -243,7 +243,7 @@ impl_for_size_integer!(isize: i64, write_i64); macro_rules! impl_for_float { ($type: ident, $method: ident) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for $type { @@ -268,7 +268,7 @@ impl_for_float!(f32, write_f32); impl_for_float!(f64, write_f64); #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for bool { @@ -287,7 +287,7 @@ impl BorshSerialize for bool { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync, @@ -321,7 +321,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync, @@ -359,7 +359,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for str { @@ -378,7 +378,7 @@ impl BorshSerialize for str { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for String { @@ -400,21 +400,21 @@ impl BorshSerialize for String { pub mod ascii { //! //! Module defines [`BorshSerialize`] - #![cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] + #![cfg_attr(feature = "unstable__async", doc = " & [`BorshSerializeAsync`]")] //! implementation for some types from [`ascii`] crate. - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use core::future::Future; use async_generic::async_generic; use super::BorshSerialize; - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use super::{AsyncWrite, BorshSerializeAsync}; use crate::io::{Result, Write}; #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for ascii::AsciiChar { @@ -433,7 +433,7 @@ pub mod ascii { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for ascii::AsciiStr { @@ -452,7 +452,7 @@ pub mod ascii { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for ascii::AsciiString { @@ -473,7 +473,7 @@ pub mod ascii { /// Helper method that is used to serialize a slice of data (without the length marker). #[inline] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_signature(data: &[T], writer: &mut W) -> Result<()> )] fn serialize_slice(data: &[T], writer: &mut W) -> Result<()> { @@ -496,7 +496,7 @@ fn serialize_slice(data: &[T], writer: &mut W) -> R } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync + Sync, @@ -520,7 +520,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for &T { @@ -538,7 +538,7 @@ impl BorshSerialize for &T { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync + ToOwned + ?Sized, @@ -563,7 +563,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync, @@ -590,7 +590,7 @@ where #[cfg(feature = "bytes")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for bytes::Bytes { @@ -610,7 +610,7 @@ impl BorshSerialize for bytes::Bytes { #[cfg(feature = "bytes")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for bytes::BytesMut { @@ -629,7 +629,7 @@ impl BorshSerialize for bytes::BytesMut { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] #[cfg(feature = "bson")] @@ -655,7 +655,7 @@ impl BorshSerialize for bson::oid::ObjectId { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync, @@ -684,7 +684,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync, @@ -718,7 +718,7 @@ where /// Module is available if borsh is built with `features = ["std"]` or `features = ["hashbrown"]`. /// /// Module defines [`BorshSerialize`] -#[cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] +#[cfg_attr(feature = "unstable__async", doc = " & [`BorshSerializeAsync`]")] /// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { @@ -727,7 +727,7 @@ pub mod hashes { use async_generic::async_generic; use super::BorshSerialize; - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use super::{AsyncWrite, BorshSerializeAsync}; use crate::{ __private::maybestd::{ @@ -739,7 +739,7 @@ pub mod hashes { }; #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where K: BorshSerializeAsync + Ord, @@ -777,7 +777,7 @@ pub mod hashes { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync + Ord, @@ -814,7 +814,7 @@ pub mod hashes { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where K: BorshSerializeAsync, @@ -852,7 +852,7 @@ where } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync + Sync, @@ -886,7 +886,7 @@ where #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for std::net::SocketAddr { @@ -918,7 +918,7 @@ impl BorshSerialize for std::net::SocketAddr { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for std::net::SocketAddrV4 { @@ -937,7 +937,7 @@ impl BorshSerialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for std::net::SocketAddrV6 { @@ -956,7 +956,7 @@ impl BorshSerialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for std::net::Ipv4Addr { @@ -982,7 +982,7 @@ impl BorshSerialize for std::net::Ipv4Addr { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for std::net::Ipv6Addr { @@ -1008,7 +1008,7 @@ impl BorshSerialize for std::net::Ipv6Addr { #[cfg(feature = "std")] #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for std::net::IpAddr { @@ -1039,7 +1039,7 @@ impl BorshSerialize for std::net::IpAddr { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync + ?Sized, @@ -1060,7 +1060,7 @@ impl BorshSerialize for Box { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync, @@ -1096,7 +1096,7 @@ where macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant )] impl BorshSerialize for $name { @@ -1112,7 +1112,7 @@ macro_rules! impl_tuple { ($($idx:tt $name:ident)+) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant<$($name),+> where $($name: BorshSerializeAsync,)+ @@ -1162,7 +1162,7 @@ impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T macro_rules! impl_range { ($type:ident, $this:ident, $($field:expr),*) => { #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync, @@ -1194,15 +1194,15 @@ impl_range!(RangeToInclusive, this, &this.end); pub mod rc { //! //! Module defines [`BorshSerialize`] - #![cfg_attr(feature = "async", doc = " & [`BorshSerializeAsync`]")] + #![cfg_attr(feature = "unstable__async", doc = " & [`BorshSerializeAsync`]")] //! implementation for [`Rc`] and [`Arc`]. - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use core::future::Future; use async_generic::async_generic; - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] use super::{AsyncWrite, BorshSerializeAsync}; use crate::{ __private::maybestd::{rc::Rc, sync::Arc}, @@ -1229,7 +1229,7 @@ pub mod rc { /// data structure. Serialization will not attempt to deduplicate these /// repeated data. #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: BorshSerializeAsync + ?Sized + Send, @@ -1246,7 +1246,7 @@ pub mod rc { } #[async_generic( - #[cfg(feature = "async")] + #[cfg(feature = "unstable__async")] async_variant where T: ?Sized + Sync, From 22b2bde2c13a4713d8a3bba944223ddf91646598 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 22:10:05 +0200 Subject: [PATCH 34/69] use `Cow<'static, str>` in place of `String` to reduce cloning --- borsh/src/nostd_io.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/borsh/src/nostd_io.rs b/borsh/src/nostd_io.rs index 280a4b930..ae87cd536 100644 --- a/borsh/src/nostd_io.rs +++ b/borsh/src/nostd_io.rs @@ -2,7 +2,7 @@ use core::{convert::From, fmt, result}; -use crate::__private::maybestd::string::String; +use crate::__private::maybestd::borrow::Cow; /// A specialized [`Result`] type for I/O operations. /// @@ -68,7 +68,7 @@ enum Repr { #[derive(Debug)] struct Custom { kind: ErrorKind, - error: String, + error: Cow<'static, str>, } /// A list specifying general categories of I/O error. @@ -228,8 +228,8 @@ impl Error { /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); /// ``` #[inline] - pub fn new>(kind: ErrorKind, error: T) -> Error { - fn new(kind: ErrorKind, error: String) -> Error { + pub fn new>>(kind: ErrorKind, error: T) -> Error { + fn new(kind: ErrorKind, error: Cow<'static, str>) -> Error { Error { repr: Repr::Custom(Custom { kind, error }), } @@ -299,7 +299,7 @@ impl Error { /// print_error(Error::new(ErrorKind::Other, "oh no!")); /// } /// ``` - pub fn into_inner(self) -> Option { + pub fn into_inner(self) -> Option> { match self.repr { Repr::Simple(..) => None, Repr::Custom(c) => Some(c.error), From b98e23d6731beeec1d37046624841861f8ae731c Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 22:22:05 +0200 Subject: [PATCH 35/69] formatting --- borsh/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index 6fa67e008..24b0c6d53 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -45,7 +45,9 @@ pub mod error; compile_error!("feature \"std\" and feature \"hashbrown\" don't make sense at the same time"); #[cfg(all(feature = "unstable__tokio", feature = "unstable__async-std"))] -compile_error!("Cannot enable both `unstable__tokio` and `unstable__async-std` features at the same time"); +compile_error!( + "Cannot enable both `unstable__tokio` and `unstable__async-std` features at the same time" +); #[cfg(feature = "std")] use std::io as io_impl; From a48e9faed1fc3d29b665c10efb2b0f7f2cc1a70d Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Wed, 29 Jan 2025 22:27:58 +0200 Subject: [PATCH 36/69] add `pub use` for derive macros for async traits --- borsh/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) 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; From 2891864f0216083bec446edc45e6d2760263ce6a Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Thu, 30 Jan 2025 13:06:21 +0200 Subject: [PATCH 37/69] Code cleanup. Reduce `quote!` usage where unnecessary. WIP: update derive macros for async traits --- .../src/internals/attributes/field/mod.rs | 12 ++++ .../src/internals/deserialize/enums/mod.rs | 34 +++++------ borsh-derive/src/internals/deserialize/mod.rs | 33 +++++++---- .../src/internals/deserialize/structs/mod.rs | 35 +++++------- .../src/internals/serialize/enums/mod.rs | 57 ++++++++++--------- borsh-derive/src/internals/serialize/mod.rs | 35 +++++++----- .../src/internals/serialize/structs/mod.rs | 41 +++++++++---- 7 files changed, 148 insertions(+), 99 deletions(-) diff --git a/borsh-derive/src/internals/attributes/field/mod.rs b/borsh-derive/src/internals/attributes/field/mod.rs index 98e4824be..7ecc2e78c 100644 --- a/borsh-derive/src/internals/attributes/field/mod.rs +++ b/borsh-derive/src/internals/attributes/field/mod.rs @@ -206,6 +206,7 @@ impl Attributes { Ok(()) } + pub(crate) fn parse(attrs: &[Attribute]) -> Result { let borsh = get_one_attribute(attrs)?; @@ -219,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 { @@ -244,6 +251,11 @@ impl Attributes { 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")] diff --git a/borsh-derive/src/internals/deserialize/enums/mod.rs b/borsh-derive/src/internals/deserialize/enums/mod.rs index 20d708a96..2d312f93c 100644 --- a/borsh-derive/src/internals/deserialize/enums/mod.rs +++ b/borsh-derive/src/internals/deserialize/enums/mod.rs @@ -1,6 +1,6 @@ -use proc_macro2::{Span, 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}; @@ -31,29 +31,30 @@ pub fn process( } 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 = if IS_ASYNC { - quote! { BorshDeserializeAsync } - } else { - quote! { BorshDeserialize } - }; - let enum_ext = if IS_ASYNC { - quote! { EnumExtAsync } - } else { - quote! { EnumExt } - }; + 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! { io::Read } }; - let async_trait = IS_ASYNC.then(|| quote! { #[::async_trait::async_trait] }); - let r#async = IS_ASYNC.then(|| syn::token::Async(Span::call_site())); + let r#async = IS_ASYNC.then(|| Token![async](Span::call_site())); let dot_await = IS_ASYNC.then(|| quote! { .await }); Ok(quote! { - #async_trait 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?; @@ -61,13 +62,12 @@ pub fn process( } } - #async_trait 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 ::core::result::Result::Err(#cratename::io::Error::new( #cratename::io::ErrorKind::InvalidData, diff --git a/borsh-derive/src/internals/deserialize/mod.rs b/borsh-derive/src/internals/deserialize/mod.rs index 07327a086..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::{parse_quote, ExprPath, Generics, Ident, Path}; +use syn::{parse_quote, ExprPath, Generics, Ident, Path, Type}; use super::{ attributes::{field, BoundType}, @@ -25,6 +25,7 @@ impl GenericsOutput { default_visitor: generics::FindTyParams::new(generics), } } + fn extend(self, where_clause: &mut syn::WhereClause, cratename: &Path) { let de_trait: Path = if IS_ASYNC { parse_quote! { #cratename::de::BorshDeserializeAsync } @@ -50,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 { @@ -67,6 +74,7 @@ fn process_field( } field_output::( field_name, + &field.ty, cratename, if IS_ASYNC { parsed.deserialize_with_async @@ -83,15 +91,20 @@ fn process_field( /// of code, which deserializes single field fn field_output( field_name: Option<&Ident>, + field_type: &Type, cratename: &Path, deserialize_with: Option, ) -> TokenStream2 { let default_path = || { - if IS_ASYNC { - parse_quote! { #cratename::BorshDeserializeAsync::deserialize_reader } - } else { - parse_quote! { #cratename::BorshDeserialize::deserialize_reader } - } + 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); diff --git a/borsh-derive/src/internals/deserialize/structs/mod.rs b/borsh-derive/src/internals/deserialize/structs/mod.rs index 1d61b7533..a016c994c 100644 --- a/borsh-derive/src/internals/deserialize/structs/mod.rs +++ b/borsh-derive/src/internals/deserialize/structs/mod.rs @@ -1,6 +1,6 @@ -use proc_macro2::{Span, 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}; @@ -25,9 +25,7 @@ pub fn process( &mut generics_output, )?; } - quote! { - Self { #body } - } + quote! { Self { #body } } } Fields::Unnamed(fields) => { for field in fields.unnamed.iter() { @@ -38,30 +36,26 @@ pub fn process( &mut generics_output, )?; } - quote! { - Self( #body ) - } - } - Fields::Unit => { - quote! { - Self {} - } + quote! { Self( #body ) } } + Fields::Unit => quote! { Self {} }, }; generics_output.extend::(&mut where_clause, &cratename); - let deserialize_trait = if IS_ASYNC { - quote! { BorshDeserializeAsync } - } else { - quote! { BorshDeserialize } - }; + 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 { quote! { io::Read } }; - let async_trait = IS_ASYNC.then(|| quote! { #[::async_trait::async_trait] }); - let r#async = IS_ASYNC.then(|| syn::token::Async(Span::call_site())); + 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! { @@ -74,7 +68,6 @@ pub fn process( }; Ok(quote! { - #async_trait 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 diff --git a/borsh-derive/src/internals/serialize/enums/mod.rs b/borsh-derive/src/internals/serialize/enums/mod.rs index 895ea8567..2523e7c48 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}, @@ -46,32 +46,30 @@ pub fn process( let fields_body = optimize_fields_body(fields_body, has_unit_variant); generics_output.extend::(&mut where_clause, &cratename); - let serialize_trait = if IS_ASYNC { - quote!(BorshSerializeAsync) - } else { - quote!(BorshSerialize) - }; + 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 async_trait = if IS_ASYNC { - quote! { #[::async_trait::async_trait] } + quote! { async_io::AsyncWrite } } else { - quote!() - }; - let r#async = if IS_ASYNC { quote!(async) } else { quote!() }; - let dot_await = if IS_ASYNC { - quote! { .await } - } else { - quote!() + quote! { io::Write } }; + let r#async = IS_ASYNC.then(|| Token![async](Span::call_site())); + let dot_await = IS_ASYNC.then(|| quote! { .await }); + let lifetime = IS_ASYNC.then(|| Lifetime::new("'async_variant", Span::call_site())); + let lt_comma = IS_ASYNC.then(|| Token![,](Span::call_site())); Ok(quote! { - #async_trait impl #impl_generics #cratename::ser::#serialize_trait for #enum_ident #ty_generics #where_clause { - #r#async fn serialize<__W: #cratename::#writer_trait>(&self, writer: &mut __W) -> ::core::result::Result<(), #cratename::io::Error> { + #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 }; @@ -215,10 +213,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 { @@ -227,6 +231,7 @@ fn process_field( if !parsed.skip { let delta = field_id.serialize_output::( + &field.ty, cratename, if IS_ASYNC { parsed.serialize_with_async diff --git a/borsh-derive/src/internals/serialize/mod.rs b/borsh-derive/src/internals/serialize/mod.rs index cc942ad5e..1ae0d4172 100644 --- a/borsh-derive/src/internals/serialize/mod.rs +++ b/borsh-derive/src/internals/serialize/mod.rs @@ -2,7 +2,7 @@ use std::convert::TryFrom; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{parse_quote, Expr, ExprPath, Generics, Ident, Index, Path}; +use syn::{parse_quote, Expr, ExprPath, Generics, Ident, Index, Path, Type}; use super::generics; @@ -79,36 +79,45 @@ impl FieldId { } } } + /// function which computes derive output [proc_macro2::TokenStream] /// of code, which serializes single field 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_some(quote! { .await }); - let serialize_trait = if IS_ASYNC { - quote! { BorshSerializeAsync } - } else { - quote! { BorshSerialize } - }; + let dot_await = IS_ASYNC.then(|| quote! { .await }); if let Some(func) = serialize_with { quote! { #func(#arg, writer)#dot_await?; } } else { - quote! { #cratename::#serialize_trait::serialize(#arg, writer)#dot_await?; } + 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 ed5790d2d..b3c8521f7 100644 --- a/borsh-derive/src/internals/serialize/structs/mod.rs +++ b/borsh-derive/src/internals/serialize/structs/mod.rs @@ -1,6 +1,6 @@ -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}, @@ -48,20 +48,29 @@ pub fn process( } generics_output.extend::(&mut where_clause, &cratename); - let serialize_trait = if IS_ASYNC { - quote! { BorshSerializeAsync } - } else { - quote! { BorshSerialize } - }; + 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::#serialize_trait for #name #ty_generics #where_clause { - fn serialize<__W: #cratename::#writer_trait_path>(&self, writer: &mut __W) -> ::core::result::Result<(), #cratename::io::Error> { + #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 ::core::result::Result::Ok(()) } @@ -77,13 +86,21 @@ 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::( + &field.ty, cratename, if IS_ASYNC { parsed.serialize_with_async From 42fd2b2897c2c1c0a66c1c2ddf3a2478c39f1ee6 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Thu, 30 Jan 2025 13:06:41 +0200 Subject: [PATCH 38/69] Add compilation tests --- .github/test.sh | 1 + .../async_derives/test_generic_enums.rs | 47 +++++++++++++++++++ .../async_derives/test_generic_structs.rs | 0 .../async_derives/test_recursive_structs.rs | 0 borsh/tests/tests.rs | 7 +++ 5 files changed, 55 insertions(+) create mode 100644 borsh/tests/compile_derives/async_derives/test_generic_enums.rs create mode 100644 borsh/tests/compile_derives/async_derives/test_generic_structs.rs create mode 100644 borsh/tests/compile_derives/async_derives/test_recursive_structs.rs diff --git a/.github/test.sh b/.github/test.sh index 2fdbf58b9..7432f0462 100755 --- a/.github/test.sh +++ b/.github/test.sh @@ -15,6 +15,7 @@ pushd borsh cargo test --no-run cargo test cargo test --features derive +cargo test --features derive,unstable__async cargo test --features unstable__schema ########## features = ["ascii"] group cargo test --features ascii 'roundtrip::test_ascii_strings' 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_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..461c7fde9 100644 --- a/borsh/tests/tests.rs +++ b/borsh/tests/tests.rs @@ -22,6 +22,13 @@ 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; + } + #[cfg(feature = "unstable__schema")] mod schema { mod test_generic_enums; From 80010843365070d969cd0da6903090d8143a090c Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Thu, 30 Jan 2025 22:10:05 +0200 Subject: [PATCH 39/69] Add default `read_exact` impl. Fix doc test --- borsh/src/async_io.rs | 17 ++++++++++++++++- borsh/src/ser/mod.rs | 4 ++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index a793941a2..66e2d3a78 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -9,7 +9,22 @@ pub trait AsyncRead: Unpin + Send { fn read_exact<'a>( &'a mut self, buf: &'a mut [u8], - ) -> impl Future> + Send + 'a; + ) -> impl Future> + Send + 'a { + async { + let mut offset = 0; + while offset < buf.len() { + let read = self.read(&mut buf[offset..]).await?; + if read == 0 { + return Err(crate::io::Error::new( + crate::io::ErrorKind::UnexpectedEof, + "failed to fill the whole buffer", + )); + } + offset += read; + } + Ok(()) + } + } fn read_u8(&mut self) -> impl Future> + Send { async { diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 959156048..88de04370 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -90,7 +90,7 @@ pub trait BorshSerialize { /// let single_serialized_buffer_len = buffer.len(); /// /// # #[cfg(feature = "derive")] -/// x.serialize(&mut buffer).unwrap(); +/// x.serialize(&mut buffer).await.unwrap(); /// # #[cfg(feature = "derive")] /// assert_eq!(buffer.len(), single_serialized_buffer_len * 2); /// @@ -99,7 +99,7 @@ pub trait BorshSerialize { /// # #[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).unwrap(); +/// x.serialize(&mut buffer_slice_enough_for_the_data).await.unwrap(); /// # }) /// ``` #[cfg(feature = "unstable__async")] From 4e04e0947bb1f4002ccc7bb92b140a041f964691 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Thu, 30 Jan 2025 23:01:23 +0200 Subject: [PATCH 40/69] Fix doc tests --- .github/test.sh | 3 ++- borsh/src/de/mod.rs | 20 ++++++++++---------- borsh/src/ser/mod.rs | 26 ++++++++++++++++---------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/.github/test.sh b/.github/test.sh index 7432f0462..6fea5344c 100755 --- a/.github/test.sh +++ b/.github/test.sh @@ -15,7 +15,8 @@ pushd borsh cargo test --no-run cargo test cargo test --features derive -cargo test --features derive,unstable__async +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/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/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")] From e13e6ef568485df2ff94dcd6f21d7d7612789291 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Fri, 31 Jan 2025 15:35:52 +0200 Subject: [PATCH 41/69] Add tests. Use `write_u8` for `variant_idx` in `BorshSerializeAsync` for enums --- .../src/internals/attributes/field/mod.rs | 60 +++++-- .../snapshots/async_bounds_parsing1-2.snap | 6 + .../snapshots/async_bounds_parsing1.snap | 6 + .../snapshots/async_bounds_parsing2-2.snap | 6 + .../snapshots/async_bounds_parsing2.snap | 6 + .../snapshots/async_bounds_parsing3.snap | 6 + .../snapshots/async_bounds_parsing4.snap | 5 + .../snapshots/async_bounds_parsing_error.snap | 7 + .../async_bounds_parsing_error2.snap | 7 + .../async_bounds_parsing_error3.snap | 7 + .../async_ser_de_with_parsing1-2.snap | 5 + .../snapshots/async_ser_de_with_parsing1.snap | 5 + .../root_bounds_and_wrong_key_combined.snap | 2 +- .../field/snapshots/root_error.snap | 2 +- .../src/internals/deserialize/enums/mod.rs | 45 ++++++ .../snapshots/borsh_discriminant_false-2.snap | 4 +- .../snapshots/borsh_discriminant_false.snap | 2 +- .../snapshots/borsh_discriminant_true-2.snap | 4 +- .../snapshots/borsh_discriminant_true.snap | 2 +- .../enums/snapshots/borsh_init_func-2.snap | 2 - .../borsh_skip_struct_variant_field-2.snap | 10 +- .../borsh_skip_struct_variant_field.snap | 6 +- .../borsh_skip_tuple_variant_field-2.snap | 9 +- .../borsh_skip_tuple_variant_field.snap | 6 +- .../enums/snapshots/bound_generics-2.snap | 18 ++- .../enums/snapshots/bound_generics.snap | 13 +- .../check_deserialize_with_async_attr-2.snap | 50 ++++++ .../check_deserialize_with_async_attr.snap | 51 ++++++ .../check_deserialize_with_attr-2.snap | 17 +- .../check_deserialize_with_attr.snap | 8 +- .../generic_borsh_skip_struct_field-2.snap | 12 +- .../generic_borsh_skip_struct_field.snap | 8 +- .../generic_borsh_skip_tuple_field-2.snap | 15 +- .../generic_borsh_skip_tuple_field.snap | 11 +- .../generic_deserialize_async_bound-2.snap | 54 +++++++ .../generic_deserialize_async_bound.snap | 51 ++++++ .../generic_deserialize_bound-2.snap | 25 +-- .../snapshots/generic_deserialize_bound.snap | 13 +- .../enums/snapshots/recursive_enum-2.snap | 18 ++- .../enums/snapshots/recursive_enum.snap | 13 +- .../simple_enum_with_custom_crate-2.snap | 25 ++- .../simple_enum_with_custom_crate.snap | 17 +- .../enums/snapshots/simple_generics-2.snap | 18 ++- .../enums/snapshots/simple_generics.snap | 13 +- .../src/internals/deserialize/structs/mod.rs | 113 ++++++++++++-- .../structs/snapshots/borsh_init_func-2.snap | 17 ++ .../structs/snapshots/borsh_init_func.snap | 4 +- .../structs/snapshots/bound_generics-2.snap | 24 +++ .../structs/snapshots/bound_generics.snap | 4 +- .../check_deserialize_with_async_attr-2.snap | 18 +++ .../check_deserialize_with_async_attr.snap | 21 +++ .../check_deserialize_with_attr-2.snap | 22 +++ .../check_deserialize_with_attr.snap | 2 +- .../generic_deserialize_async_bound-2.snap | 23 +++ .../generic_deserialize_async_bound.snap | 18 +++ .../generic_deserialize_bound-2.snap | 23 +++ .../snapshots/generic_deserialize_bound.snap | 4 +- ...eric_named_fields_struct_borsh_skip-2.snap | 19 +++ ...eneric_named_fields_struct_borsh_skip.snap | 2 +- .../generic_tuple_struct_borsh_skip1-2.snap | 21 +++ .../generic_tuple_struct_borsh_skip1.snap | 2 +- .../generic_tuple_struct_borsh_skip2-2.snap | 25 +++ .../generic_tuple_struct_borsh_skip2.snap | 2 +- ...e_automatically_added_default_trait-2.snap | 21 +++ ...ide_automatically_added_default_trait.snap | 2 +- ...matically_added_default_trait_async-2.snap | 19 +++ ...tomatically_added_default_trait_async.snap | 21 +++ .../structs/snapshots/recursive_struct-2.snap | 19 +++ .../structs/snapshots/recursive_struct.snap | 7 +- .../simple_generic_tuple_struct-2.snap | 19 +++ .../simple_generic_tuple_struct.snap | 4 +- .../structs/snapshots/simple_generics-2.snap | 23 +++ .../structs/snapshots/simple_generics.snap | 4 +- .../structs/snapshots/simple_struct-2.snap | 15 ++ .../structs/snapshots/simple_struct.snap | 4 +- .../simple_struct_with_custom_crate-2.snap | 20 +++ .../simple_struct_with_custom_crate.snap | 6 +- .../src/internals/schema/structs/mod.rs | 14 +- .../src/internals/serialize/enums/mod.rs | 119 ++++++++++++-- .../snapshots/borsh_discriminant_false-2.snap | 21 +++ .../snapshots/borsh_discriminant_true-2.snap | 21 +++ ...orsh_skip_struct_variant_all_fields-2.snap | 23 +++ .../borsh_skip_struct_variant_all_fields.snap | 2 +- .../borsh_skip_struct_variant_field-2.snap | 25 +++ .../borsh_skip_struct_variant_field.snap | 4 +- .../borsh_skip_tuple_variant_field-2.snap | 23 +++ .../borsh_skip_tuple_variant_field.snap | 2 +- .../enums/snapshots/bound_generics-2.snap | 34 ++++ .../enums/snapshots/bound_generics.snap | 8 +- .../check_serialize_with_async_attr-2.snap | 31 ++++ .../check_serialize_with_async_attr.snap | 31 ++++ .../check_serialize_with_attr-2.snap | 32 ++++ .../snapshots/check_serialize_with_attr.snap | 6 +- .../generic_borsh_skip_struct_field-2.snap | 31 ++++ .../generic_borsh_skip_struct_field.snap | 6 +- .../generic_borsh_skip_tuple_field-2.snap | 32 ++++ .../generic_borsh_skip_tuple_field.snap | 6 +- .../generic_serialize_async_bound-2.snap | 32 ++++ .../generic_serialize_async_bound.snap | 31 ++++ .../snapshots/generic_serialize_bound-2.snap | 32 ++++ .../snapshots/generic_serialize_bound.snap | 8 +- .../snapshots/mixed_with_unit_variants-2.snap | 29 ++++ .../snapshots/mixed_with_unit_variants.snap | 6 +- .../enums/snapshots/recursive_enum-2.snap | 33 ++++ .../enums/snapshots/recursive_enum.snap | 8 +- .../simple_enum_with_custom_crate-2.snap | 32 ++++ .../simple_enum_with_custom_crate.snap | 6 +- .../enums/snapshots/simple_generics-2.snap | 33 ++++ .../enums/snapshots/simple_generics.snap | 8 +- .../snapshots/struct_variant_field-2.snap | 26 ++++ .../enums/snapshots/struct_variant_field.snap | 6 +- .../src/internals/serialize/structs/mod.rs | 147 ++++++++++++++++-- ...eneric_associated_type_wrong_derive-2.snap | 23 +++ ..._generic_associated_type_wrong_derive.snap | 22 +++ .../structs/snapshots/bound_generics-2.snap | 19 +++ .../structs/snapshots/bound_generics.snap | 4 +- .../check_serialize_with_async_attr-2.snap | 18 +++ .../check_serialize_with_async_attr.snap | 18 +++ ..._serialize_with_async_skip_conflict-2.snap | 7 + ...ck_serialize_with_async_skip_conflict.snap | 7 + .../check_serialize_with_attr-2.snap | 19 +++ .../snapshots/check_serialize_with_attr.snap | 2 +- .../check_serialize_with_skip_conflict-2.snap | 7 + .../snapshots/generic_associated_type.snap | 4 +- ...eric_named_fields_struct_borsh_skip-2.snap | 16 ++ ...eneric_named_fields_struct_borsh_skip.snap | 2 +- .../generic_serialize_async_bound-2.snap | 18 +++ .../generic_serialize_async_bound.snap | 18 +++ .../snapshots/generic_serialize_bound-2.snap | 18 +++ .../snapshots/generic_serialize_bound.snap | 4 +- .../generic_tuple_struct_borsh_skip1-2.snap | 16 ++ .../generic_tuple_struct_borsh_skip1.snap | 2 +- .../generic_tuple_struct_borsh_skip2-2.snap | 17 ++ .../generic_tuple_struct_borsh_skip2.snap | 2 +- ...eneric_associated_type_wrong_derive-2.snap | 23 +++ ..._generic_associated_type_wrong_derive.snap | 7 +- .../structs/snapshots/recursive_struct-2.snap | 18 +++ .../structs/snapshots/recursive_struct.snap | 4 +- .../simple_generic_tuple_struct-2.snap | 17 ++ .../simple_generic_tuple_struct.snap | 4 +- .../structs/snapshots/simple_generics-2.snap | 18 +++ .../structs/snapshots/simple_generics.snap | 4 +- .../structs/snapshots/simple_struct-2.snap | 14 ++ .../structs/snapshots/simple_struct.snap | 4 +- .../simple_struct_with_custom_crate-2.snap | 16 ++ .../simple_struct_with_custom_crate.snap | 4 +- .../test_macro_namespace_collisions.rs | 21 +++ borsh/tests/tests.rs | 1 + 148 files changed, 2273 insertions(+), 271 deletions(-) create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1-2.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing1.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2-2.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing2.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing3.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing4.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error2.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_bounds_parsing_error3.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1-2.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/async_ser_de_with_parsing1.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/check_deserialize_with_async_attr.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound-2.snap create mode 100644 borsh-derive/src/internals/deserialize/enums/snapshots/generic_deserialize_async_bound.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/borsh_init_func-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_async_attr.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/check_deserialize_with_attr-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_async_bound.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/generic_deserialize_bound-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/override_automatically_added_default_trait_async.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/simple_generic_tuple_struct-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct-2.snap create mode 100644 borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct_with_custom_crate-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_false-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/borsh_discriminant_true-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_all_fields-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_struct_variant_field-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/borsh_skip_tuple_variant_field-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/bound_generics-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_async_attr.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/check_serialize_with_attr-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_struct_field-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/generic_borsh_skip_tuple_field-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_async_bound.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/generic_serialize_bound-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/mixed_with_unit_variants-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/simple_enum_with_custom_crate-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/simple_generics-2.snap create mode 100644 borsh-derive/src/internals/serialize/enums/snapshots/struct_variant_field-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/async_override_generic_associated_type_wrong_derive.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/bound_generics-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_attr.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_async_skip_conflict.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_attr-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/generic_named_fields_struct_borsh_skip-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_async_bound.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/generic_serialize_bound-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip1-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/generic_tuple_struct_borsh_skip2-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/override_generic_associated_type_wrong_derive-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/simple_generic_tuple_struct-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/simple_generics-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/simple_struct-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/simple_struct_with_custom_crate-2.snap create mode 100644 borsh/tests/compile_derives/async_derives/test_macro_namespace_collisions.rs diff --git a/borsh-derive/src/internals/attributes/field/mod.rs b/borsh-derive/src/internals/attributes/field/mod.rs index 7ecc2e78c..739059c29 100644 --- a/borsh-derive/src/internals/attributes/field/mod.rs +++ b/borsh-derive/src/internals/attributes/field/mod.rs @@ -317,6 +317,12 @@ impl Attributes { mod tests { 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, + }; + struct ParsedBounds { common: Option, r#async: Option, @@ -331,12 +337,6 @@ mod tests { }) } - 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, - }; - #[test] fn test_reject_multiple_borsh_attrs() { let item_struct: ItemStruct = parse_quote! { @@ -475,7 +475,7 @@ mod tests { fn test_bounds_parsing_error3() { let item_struct: ItemStruct = parse_quote! { struct A { - #[borsh(async_bound(deserialize = 42))] + #[borsh(bound(deserialize = 42))] x: u64, y: String, } @@ -493,9 +493,12 @@ mod tests { fn test_async_bounds_parsing1() { let item_struct: ItemStruct = parse_quote! { struct A { - #[borsh(async_bound(deserialize = "K: Hash + Ord, + #[borsh(async_bound( + deserialize = + "K: Hash + Ord, V: Eq + Ord", - serialize = "K: Hash + Eq + Ord, + serialize = + "K: Hash + Eq + Ord, V: Ord" ))] x: u64, @@ -513,10 +516,12 @@ mod tests { fn test_async_bounds_parsing2() { let item_struct: ItemStruct = parse_quote! { struct A { - #[borsh(async_bound(deserialize = "K: Hash + Eq + borsh::de::BorshDeserialize, - V: borsh::de::BorshDeserialize", - serialize = "K: Hash + Eq + borsh::ser::BorshSerialize, - V: borsh::ser::BorshSerialize" + #[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, @@ -533,8 +538,9 @@ mod tests { fn test_async_bounds_parsing3() { let item_struct: ItemStruct = parse_quote! { struct A { - #[borsh(async_bound(deserialize = "K: Hash + Eq + borsh::de::BorshDeserialize, - V: borsh::de::BorshDeserialize", + #[borsh(async_bound(deserialize = + "K: Hash + Eq + borsh::de::BorshDeserializeAsync, + V: borsh::de::BorshDeserializeAsync", serialize = "" ))] x: u64, @@ -636,6 +642,26 @@ mod tests { 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 = parse_quote! { @@ -651,6 +677,7 @@ mod tests { let result = Attributes::parse(&first_field.attrs).unwrap(); assert!(result.skip); } + #[test] fn test_borsh_no_skip() { let item_struct: ItemStruct = parse_quote! { @@ -680,6 +707,7 @@ mod tests_schema { local_insta_assert_debug_snapshot, local_insta_assert_snapshot, }, }; + fn parse_schema_attrs(attrs: &[Attribute]) -> Result, syn::Error> { // #[borsh(schema(params = "..."))] let borsh_attrs = Attributes::parse(attrs)?; @@ -731,6 +759,7 @@ mod tests_schema { 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 = parse_quote! { @@ -796,6 +825,7 @@ mod tests_schema { 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 = parse_quote! { 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/deserialize/enums/mod.rs b/borsh-derive/src/internals/deserialize/enums/mod.rs index 2d312f93c..925d73301 100644 --- a/borsh-derive/src/internals/deserialize/enums/mod.rs +++ b/borsh-derive/src/internals/deserialize/enums/mod.rs @@ -294,6 +294,29 @@ mod tests { 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_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_attr() { let item_enum: ItemEnum = parse_quote! { @@ -314,6 +337,26 @@ mod tests { 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_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 borsh_discriminant_false() { let item_enum: ItemEnum = parse_quote! { @@ -334,6 +377,7 @@ mod tests { 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 = parse_quote! { @@ -354,6 +398,7 @@ mod tests { 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 = parse_quote! { 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 index 1c9faef60..2d8c2ec53 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for X { async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( reader: &mut __R, @@ -12,13 +11,12 @@ impl borsh::de::BorshDeserializeAsync for X { ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] 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 mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { X::A } else if variant_tag == 1u8 { X::B 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 6ceab9cb0..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 @@ -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 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 index 98bd8cfdb..5a617705e 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for X { async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( reader: &mut __R, @@ -12,13 +11,12 @@ impl borsh::de::BorshDeserializeAsync for X { ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] 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 mut return_value = if variant_tag == 0 { + let return_value = if variant_tag == 0 { X::A } else if variant_tag == 20 { X::B 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 e62028c67..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 @@ -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 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 index 89943b024..dec3fd255 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for A { async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( reader: &mut __R, @@ -12,7 +11,6 @@ impl borsh::de::BorshDeserializeAsync for A { ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for A { async fn deserialize_variant<__R: borsh::async_io::AsyncRead>( reader: &mut __R, 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 index 6b54de688..b95070208 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for AA { async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( reader: &mut __R, @@ -12,20 +11,21 @@ impl borsh::de::BorshDeserializeAsync for AA { ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] 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 mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { AA::B { c: ::core::default::Default::default(), - d: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + d: ::deserialize_reader(reader) + .await?, } } else if variant_tag == 1u8 { AA::NegatedVariant { - beta: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + beta: ::deserialize_reader(reader) + .await?, } } else { return ::core::result::Result::Err( 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 040c9bf70..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 @@ -15,14 +15,14 @@ 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)?, + d: ::deserialize_reader(reader)?, } } else if variant_tag == 1u8 { AA::NegatedVariant { - beta: borsh::BorshDeserialize::deserialize_reader(reader)?, + beta: ::deserialize_reader(reader)?, } } else { return ::core::result::Result::Err( 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 index 5e2b62fee..51758af91 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for AAT { async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( reader: &mut __R, @@ -12,20 +11,20 @@ impl borsh::de::BorshDeserializeAsync for AAT { ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] 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 mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { AAT::B( ::core::default::Default::default(), - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, ) } else if variant_tag == 1u8 { AAT::NegatedVariant { - beta: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + beta: ::deserialize_reader(reader) + .await?, } } else { return ::core::result::Result::Err( 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 ce2969dc8..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 @@ -15,14 +15,14 @@ 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)?, + ::deserialize_reader(reader)?, ) } else if variant_tag == 1u8 { AAT::NegatedVariant { - beta: borsh::BorshDeserialize::deserialize_reader(reader)?, + beta: ::deserialize_reader(reader)?, } } else { return ::core::result::Result::Err( 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 index 1d20e873c..1b3648e82 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics-2.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics-2.snap @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for A where V: Value, @@ -18,7 +17,6 @@ where ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for A where V: Value, @@ -30,15 +28,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::BorshDeserializeAsync::deserialize_reader(reader).await?, - y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, ) } else { return ::core::result::Result::Err( 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 5cc05304f..abae695c1 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/bound_generics.snap @@ -27,15 +27,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 { 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 ::core::result::Result::Err( 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 index a96e5e3d6..4be6ba10b 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for C where K: borsh::de::BorshDeserializeAsync, @@ -16,7 +15,6 @@ where ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for C where K: borsh::de::BorshDeserializeAsync, @@ -26,15 +24,20 @@ 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::BorshDeserializeAsync::deserialize_reader(reader).await?, - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, ) } else if variant_tag == 1u8 { C::C4 { - x: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, - y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + x: ::deserialize_reader(reader) + .await?, + y: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, } } else { return ::core::result::Result::Err( 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 495349816..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 @@ -23,14 +23,14 @@ 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 { 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 index 4447960e0..4329633ca 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for A where V: Value, @@ -19,7 +18,6 @@ where ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for A where V: Value, @@ -32,15 +30,17 @@ 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: ::core::default::Default::default(), - y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + y: ::deserialize_reader(reader) + .await?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, ) } else { return ::core::result::Result::Err( 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 a28dd1d24..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 @@ -29,15 +29,15 @@ 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: ::core::default::Default::default(), - y: 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 ::core::result::Result::Err( 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 index a75f18467..0910625cb 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for A where V: Value, @@ -18,7 +17,6 @@ where ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for A where V: Value, @@ -30,14 +28,19 @@ 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::BorshDeserializeAsync::deserialize_reader(reader).await?, - y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, ::core::default::Default::default(), ) } else { 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 2a1711d79..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 @@ -27,14 +27,17 @@ 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)?, + ::deserialize_reader(reader)?, ::core::default::Default::default(), ) } else { 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 index 42989fee7..0eedb6981 100644 --- 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 @@ -2,11 +2,10 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for A where - T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize, - U: borsh::de::BorshDeserialize, + T: borsh::de::BorshDeserializeAsync, + U: borsh::de::BorshDeserializeAsync, { async fn deserialize_reader<__R: borsh::async_io::AsyncRead>( reader: &mut __R, @@ -16,25 +15,29 @@ where ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for A where - T: PartialOrd + Hash + Eq + borsh::de::BorshDeserialize, - U: borsh::de::BorshDeserialize, + 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 mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::C { - a: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, - b: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + a: ::deserialize_reader(reader) + .await?, + b: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, } } else if variant_tag == 1u8 { A::D( - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, ) } else { return ::core::result::Result::Err( 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 36f3667dd..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 @@ -23,15 +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 { 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 ::core::result::Result::Err( 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 index ce04d99b9..705858356 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum-2.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum-2.snap @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for A where V: Value, @@ -17,7 +16,6 @@ where ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for A where V: Value, @@ -28,15 +26,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::BorshDeserializeAsync::deserialize_reader(reader).await?, - y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, ) } else { return ::core::result::Result::Err( 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 5ccc804be..852382274 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/recursive_enum.snap @@ -25,15 +25,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 { 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 ::core::result::Result::Err( 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 index 2c0a88011..a6eb2c787 100644 --- 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 @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl reexporter::borsh::de::BorshDeserializeAsync for A { async fn deserialize_reader<__R: reexporter::borsh::async_io::AsyncRead>( reader: &mut __R, @@ -15,24 +14,36 @@ impl reexporter::borsh::de::BorshDeserializeAsync for A { .await } } -#[::async_trait::async_trait] 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 mut return_value = if variant_tag == 0u8 { + let return_value = if variant_tag == 0u8 { A::B { - x: reexporter::borsh::BorshDeserializeAsync::deserialize_reader(reader) + x: as reexporter::borsh::BorshDeserializeAsync>::deserialize_reader( + reader, + ) .await?, - y: reexporter::borsh::BorshDeserializeAsync::deserialize_reader(reader) + y: ::deserialize_reader( + reader, + ) .await?, } } else if variant_tag == 1u8 { A::C( - reexporter::borsh::BorshDeserializeAsync::deserialize_reader(reader) + ::deserialize_reader( + reader, + ) .await?, - reexporter::borsh::BorshDeserializeAsync::deserialize_reader(reader) + as reexporter::borsh::BorshDeserializeAsync>::deserialize_reader( + reader, + ) .await?, ) } else { 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 36de9b1d5..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 @@ -17,15 +17,22 @@ 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 ::core::result::Result::Err( 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 index 1ec3afbc0..e39c1335d 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics-2.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics-2.snap @@ -2,7 +2,6 @@ source: borsh-derive/src/internals/deserialize/enums/mod.rs expression: pretty_print_syn_str(actual).unwrap() --- -#[::async_trait::async_trait] impl borsh::de::BorshDeserializeAsync for A where K: borsh::de::BorshDeserializeAsync, @@ -17,7 +16,6 @@ where ::deserialize_variant(reader, tag).await } } -#[::async_trait::async_trait] impl borsh::de::EnumExtAsync for A where K: borsh::de::BorshDeserializeAsync, @@ -28,15 +26,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::BorshDeserializeAsync::deserialize_reader(reader).await?, - y: borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + x: as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, + y: ::deserialize_reader(reader) + .await?, } } else if variant_tag == 1u8 { A::C( - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, - borsh::BorshDeserializeAsync::deserialize_reader(reader).await?, + ::deserialize_reader(reader).await?, + as borsh::BorshDeserializeAsync>::deserialize_reader(reader) + .await?, ) } else { return ::core::result::Result::Err( 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 2ea9415ea..ef9765ea6 100644 --- a/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/deserialize/enums/snapshots/simple_generics.snap @@ -25,15 +25,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 { 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 ::core::result::Result::Err( diff --git a/borsh-derive/src/internals/deserialize/structs/mod.rs b/borsh-derive/src/internals/deserialize/structs/mod.rs index a016c994c..759628f76 100644 --- a/borsh-derive/src/internals/deserialize/structs/mod.rs +++ b/borsh-derive/src/internals/deserialize/structs/mod.rs @@ -94,8 +94,10 @@ mod tests { } }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -109,8 +111,11 @@ mod tests { }; let crate_: Path = parse_quote! { reexporter::borsh }; - let actual = process::(item_struct, crate_).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()); } @@ -123,7 +128,10 @@ mod tests { } }; - 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()); + + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -133,7 +141,10 @@ mod tests { struct TupleA(T, u32); }; - 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()); + + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -146,7 +157,10 @@ mod tests { } }; - 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()); + + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -159,8 +173,10 @@ mod tests { } }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -174,8 +190,10 @@ mod tests { ); }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -189,8 +207,10 @@ mod tests { ); }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -204,8 +224,10 @@ mod tests { } }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -222,8 +244,30 @@ mod tests { } }; - 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()); + + 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.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()); } @@ -237,8 +281,27 @@ mod tests { ); }; - 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()); + + 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.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()); } @@ -252,10 +315,30 @@ mod tests { } }; - 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()); + + 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_struct: ItemStruct = parse_quote! { @@ -265,7 +348,11 @@ mod tests { y: String, } }; - 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()); + + 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 8ddc9e728..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 @@ -7,8 +7,8 @@ impl borsh::de::BorshDeserialize for A { 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(); ::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 232936337..81363ce72 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/bound_generics.snap @@ -12,8 +12,8 @@ where reader: &mut __R, ) -> ::core::result::Result { ::core::result::Result::Ok(Self { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + 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 25e053721..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 @@ -12,7 +12,7 @@ where ) -> ::core::result::Result { ::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 dc7c2ce92..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 @@ -11,8 +11,8 @@ where reader: &mut __R, ) -> ::core::result::Result { ::core::result::Result::Ok(Self { - a: borsh::BorshDeserialize::deserialize_reader(reader)?, - b: borsh::BorshDeserialize::deserialize_reader(reader)?, + 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 17e3635c6..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 @@ -13,7 +13,7 @@ where ) -> ::core::result::Result { ::core::result::Result::Ok(Self { x: ::core::default::Default::default(), - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + 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 dcacef19b..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 @@ -14,7 +14,7 @@ where ::core::result::Result::Ok( Self( ::core::default::Default::default(), - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::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 823d05e41..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 @@ -13,7 +13,7 @@ where ) -> ::core::result::Result { ::core::result::Result::Ok( Self( - borsh::BorshDeserialize::deserialize_reader(reader)?, + 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 c8556e104..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 @@ -12,7 +12,7 @@ where ::core::result::Result::Ok( Self( ::core::default::Default::default(), - borsh::BorshDeserialize::deserialize_reader(reader)?, + ::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 b2ea3a66f..2336313ce 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/recursive_struct.snap @@ -7,8 +7,11 @@ impl borsh::de::BorshDeserialize for CRecC { reader: &mut __R, ) -> ::core::result::Result { ::core::result::Result::Ok(Self { - a: borsh::BorshDeserialize::deserialize_reader(reader)?, - b: borsh::BorshDeserialize::deserialize_reader(reader)?, + 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 48b801d82..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 @@ -11,8 +11,8 @@ where ) -> ::core::result::Result { ::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 e73fa05df..e1566514c 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_generics.snap @@ -11,8 +11,8 @@ where reader: &mut __R, ) -> ::core::result::Result { ::core::result::Result::Ok(Self { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + 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 367c83c1c..feaaa0d5e 100644 --- a/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap +++ b/borsh-derive/src/internals/deserialize/structs/snapshots/simple_struct.snap @@ -7,8 +7,8 @@ impl borsh::de::BorshDeserialize for A { reader: &mut __R, ) -> ::core::result::Result { ::core::result::Result::Ok(Self { - x: borsh::BorshDeserialize::deserialize_reader(reader)?, - y: borsh::BorshDeserialize::deserialize_reader(reader)?, + 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 e85cdfed5..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 @@ -7,8 +7,10 @@ impl reexporter::borsh::de::BorshDeserialize for A { reader: &mut __R, ) -> ::core::result::Result { ::core::result::Result::Ok(Self { - x: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, - y: reexporter::borsh::BorshDeserialize::deserialize_reader(reader)?, + x: ::deserialize_reader(reader)?, + y: ::deserialize_reader( + reader, + )?, }) } } diff --git a/borsh-derive/src/internals/schema/structs/mod.rs b/borsh-derive/src/internals/schema/structs/mod.rs index 40a760b28..19b09f5b6 100644 --- a/borsh-derive/src/internals/schema/structs/mod.rs +++ b/borsh-derive/src/internals/schema/structs/mod.rs @@ -13,10 +13,9 @@ fn field_declaration_output( cratename: &Path, declaration_override: Option, ) -> TokenStream2 { - let default_path: ExprPath = - parse_quote! { <#field_type as #cratename::BorshSchema>::declaration }; + 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,11 +36,9 @@ 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); @@ -135,6 +132,7 @@ fn process_fields( } Ok((struct_fields, add_definitions_recursively)) } + fn process_field( field: &syn::Field, cratename: &Path, diff --git a/borsh-derive/src/internals/serialize/enums/mod.rs b/borsh-derive/src/internals/serialize/enums/mod.rs index 2523e7c48..0eee414f3 100644 --- a/borsh-derive/src/internals/serialize/enums/mod.rs +++ b/borsh-derive/src/internals/serialize/enums/mod.rs @@ -60,10 +60,15 @@ pub fn process( quote! { io::Write } }; let r#async = IS_ASYNC.then(|| Token![async](Span::call_site())); - let dot_await = IS_ASYNC.then(|| quote! { .await }); 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::#serialize_trait for #enum_ident #ty_generics #where_clause { #r#async fn serialize<#lifetime #lt_comma __W: #cratename::#writer_trait>( @@ -73,7 +78,7 @@ pub fn process( let variant_idx: u8 = match self { #all_variants_idx_body }; - writer.write_all(&variant_idx.to_le_bytes())#dot_await?; + #write_variant_idx?; #fields_body ::core::result::Result::Ok(()) @@ -266,8 +271,11 @@ mod tests { } } }; - 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()); + + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -286,8 +294,10 @@ mod tests { } }; - 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()); + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -307,8 +317,11 @@ mod tests { }; let crate_: Path = parse_quote! { reexporter::borsh }; - 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()); + + let actual = process::(item_enum, crate_).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -330,8 +343,10 @@ mod tests { } }; - 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()); + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -354,8 +369,10 @@ mod tests { } }; - 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()); + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -371,7 +388,10 @@ mod tests { } }; - 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()); + + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -387,7 +407,10 @@ mod tests { } }; - 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()); + + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -403,8 +426,10 @@ mod tests { } }; - 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()); + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -421,8 +446,10 @@ mod tests { } }; - 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()); + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -438,8 +465,10 @@ mod tests { } }; - 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()); + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -459,8 +488,33 @@ mod tests { } }; - 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()); + + 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_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()); } @@ -477,8 +531,30 @@ mod tests { } }; - 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()); + 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_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()); } @@ -495,8 +571,11 @@ mod tests { F, } }; - 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()); + + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } #[test] @@ -512,8 +591,11 @@ mod tests { F, } }; - 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()); + + let actual = process::(item_enum, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -527,8 +609,11 @@ mod tests { D, } }; - 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()); + + 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_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_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 51f0d5c37..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 @@ -15,7 +15,7 @@ impl borsh::ser::BorshSerialize for AAB { match self { AAB::B { .. } => {} AAB::NegatedVariant { beta, .. } => { - borsh::BorshSerialize::serialize(beta, writer)?; + ::serialize(beta, writer)?; } } ::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 af35f501a..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 @@ -14,10 +14,10 @@ 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)?; } } ::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 202707f5b..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 @@ -15,7 +15,7 @@ impl borsh::ser::BorshSerialize for AATTB { match self { AATTB::B(_id0, _id1) => {} AATTB::NegatedVariant { beta, .. } => { - borsh::BorshSerialize::serialize(beta, writer)?; + ::serialize(beta, writer)?; } } ::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 76c134aa7..10e186ddc 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/bound_generics.snap @@ -20,12 +20,12 @@ 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)?; } } ::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 4f1582a8c..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 @@ -18,11 +18,11 @@ 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)?; } } 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 244488064..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 @@ -19,11 +19,11 @@ 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)?; } } ::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 ac1f1c6fc..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 @@ -19,11 +19,11 @@ 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)?; } } ::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 54fff0c5e..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 @@ -18,12 +18,12 @@ 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)?; } } ::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 b1295d8b1..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 @@ -16,11 +16,11 @@ 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)?; } _ => {} } 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 320d2a29f..6724928e5 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/recursive_enum.snap @@ -19,12 +19,12 @@ 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)?; } } ::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 20fe3f9b0..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 @@ -14,11 +14,11 @@ 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)?; } } ::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 a7073cbf7..8d056af5e 100644 --- a/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/serialize/enums/snapshots/simple_generics.snap @@ -19,12 +19,12 @@ 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)?; } } ::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 44998ce45..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 @@ -14,11 +14,11 @@ 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)?; } } ::core::result::Result::Ok(()) diff --git a/borsh-derive/src/internals/serialize/structs/mod.rs b/borsh-derive/src/internals/serialize/structs/mod.rs index b3c8521f7..7fb87ce4c 100644 --- a/borsh-derive/src/internals/serialize/structs/mod.rs +++ b/borsh-derive/src/internals/serialize/structs/mod.rs @@ -136,8 +136,10 @@ mod tests { } }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -151,8 +153,11 @@ mod tests { }; let crate_: Path = parse_quote! { reexporter::borsh }; - let actual = process::(item_struct, crate_).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()); } @@ -165,7 +170,10 @@ mod tests { } }; - 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()); + + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -175,7 +183,10 @@ mod tests { struct TupleA(T, u32); }; - 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()); + + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -188,7 +199,10 @@ mod tests { } }; - 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()); + + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -201,8 +215,10 @@ mod tests { } }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -216,8 +232,10 @@ mod tests { ); }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -231,8 +249,10 @@ mod tests { ); }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -246,8 +266,10 @@ mod tests { } }; - 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()); + let actual = process::(item_struct, default_cratename()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); } @@ -281,8 +303,30 @@ mod tests { } }; - 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()); + 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()); } @@ -298,8 +342,29 @@ mod tests { } }; - 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()); + 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.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()); } @@ -313,8 +378,27 @@ mod tests { } }; - 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()); + + 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.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()); } @@ -322,13 +406,48 @@ mod tests { fn check_serialize_with_skip_conflict() { 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, + } + }; + + 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, default_cratename()); + 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"), 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 2b980a463..15a8d413d 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/bound_generics.snap @@ -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)?; + 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 19182d8bb..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 @@ -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)?; + ::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/generic_associated_type.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type.snap index 518aa61a7..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 @@ -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)?; + ::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 fc41a7cfc..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 @@ -10,7 +10,7 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.y, writer)?; + ::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 112bd5cd2..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 @@ -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)?; + ::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 852a4e452..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 @@ -10,7 +10,7 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.1, writer)?; + ::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 ab4dc9312..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 @@ -11,7 +11,7 @@ where &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.0, writer)?; + 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 7de5e9c97..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 @@ -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)?; + <::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 beb4a1f5c..33be64902 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/recursive_struct.snap @@ -7,8 +7,8 @@ impl borsh::ser::BorshSerialize for CRecC { &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.a, writer)?; - borsh::BorshSerialize::serialize(&self.b, writer)?; + ::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 f7cfd69d2..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 @@ -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)?; + ::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 12c26f9e9..47667b80d 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_generics.snap @@ -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)?; + 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 dd36b7e50..eac613281 100644 --- a/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct.snap +++ b/borsh-derive/src/internals/serialize/structs/snapshots/simple_struct.snap @@ -7,8 +7,8 @@ impl borsh::ser::BorshSerialize for A { &self, writer: &mut __W, ) -> ::core::result::Result<(), borsh::io::Error> { - borsh::BorshSerialize::serialize(&self.x, writer)?; - borsh::BorshSerialize::serialize(&self.y, writer)?; + ::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 6e84fd5da..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 @@ -7,8 +7,8 @@ impl reexporter::borsh::ser::BorshSerialize for A { &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)?; + ::serialize(&self.x, writer)?; + ::serialize(&self.y, writer)?; ::core::result::Result::Ok(()) } } 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/tests.rs b/borsh/tests/tests.rs index 461c7fde9..e82d7e98b 100644 --- a/borsh/tests/tests.rs +++ b/borsh/tests/tests.rs @@ -27,6 +27,7 @@ mod compile_derives { mod test_generic_structs; mod test_generic_enums; mod test_recursive_structs; + mod test_macro_namespace_collisions; } #[cfg(feature = "unstable__schema")] From 6c78116060b0d0a1ad3a8548b4a0030d5f61cad3 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Fri, 31 Jan 2025 15:37:46 +0200 Subject: [PATCH 42/69] fmt --- borsh-derive/src/internals/serialize/structs/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borsh-derive/src/internals/serialize/structs/mod.rs b/borsh-derive/src/internals/serialize/structs/mod.rs index 7fb87ce4c..75dc88893 100644 --- a/borsh-derive/src/internals/serialize/structs/mod.rs +++ b/borsh-derive/src/internals/serialize/structs/mod.rs @@ -153,7 +153,7 @@ mod tests { }; let crate_: Path = parse_quote! { reexporter::borsh }; - + let actual = process::(item_struct.clone(), crate_.clone()).unwrap(); local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); From 475a6cebc4bc9f22d4cb378e4c0db54ff42e2486 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 12:43:48 +0200 Subject: [PATCH 43/69] Revert rustfmt.toml --- rustfmt.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 4d94d105b..36c419bb3 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,4 +1 @@ -edition = "2021" -unstable_features = true -group_imports = "StdExternalCrate" -imports_granularity = "Crate" \ No newline at end of file +edition = "2021" \ No newline at end of file From 8419d81f816905830defdfcd624b87b4e42c09bf Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 12:44:37 +0200 Subject: [PATCH 44/69] Parametrize `needs_bounds_derive` and `collect_bounds` with `IS_ASYNC` --- .../src/internals/attributes/field/mod.rs | 30 ++++--------------- borsh-derive/src/internals/deserialize/mod.rs | 14 +++------ .../src/internals/serialize/enums/mod.rs | 14 +++------ .../src/internals/serialize/structs/mod.rs | 14 +++------ 4 files changed, 18 insertions(+), 54 deletions(-) diff --git a/borsh-derive/src/internals/attributes/field/mod.rs b/borsh-derive/src/internals/attributes/field/mod.rs index 739059c29..f7c4d74df 100644 --- a/borsh-derive/src/internals/attributes/field/mod.rs +++ b/borsh-derive/src/internals/attributes/field/mod.rs @@ -221,39 +221,21 @@ impl Attributes { Ok(result) } - pub(crate) fn needs_bounds_derive(&self, ty: BoundType) -> bool { - let predicates = self.get_bounds(ty); + 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 { - BoundType::Serialize => bounds.serialize.clone(), - BoundType::Deserialize => bounds.deserialize.clone(), - }) - } - - fn get_async_bounds(&self, ty: BoundType) -> Option> { - let bounds = self.async_bounds.as_ref(); + fn get_bounds(&self, ty: BoundType) -> Option> { + let bounds = if IS_ASYNC { self.async_bounds.as_ref() } else { self.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); + pub(crate) fn collect_bounds(&self, ty: BoundType) -> Vec { + let predicates = self.get_bounds::(ty); predicates.unwrap_or_default() } } diff --git a/borsh-derive/src/internals/deserialize/mod.rs b/borsh-derive/src/internals/deserialize/mod.rs index 166841979..d544d0ffd 100644 --- a/borsh-derive/src/internals/deserialize/mod.rs +++ b/borsh-derive/src/internals/deserialize/mod.rs @@ -51,16 +51,10 @@ fn process_field( ) -> syn::Result<()> { let parsed = field::Attributes::parse(&field.attrs)?; - 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) - }; + generics + .overrides + .extend(parsed.collect_bounds::(BoundType::Deserialize)); + let needs_bounds_derive = parsed.needs_bounds_derive::(BoundType::Deserialize); let field_name = field.ident.as_ref(); let delta = if parsed.skip { diff --git a/borsh-derive/src/internals/serialize/enums/mod.rs b/borsh-derive/src/internals/serialize/enums/mod.rs index 0eee414f3..76c2ae923 100644 --- a/borsh-derive/src/internals/serialize/enums/mod.rs +++ b/borsh-derive/src/internals/serialize/enums/mod.rs @@ -218,16 +218,10 @@ fn process_field( ) -> syn::Result<()> { let parsed = field::Attributes::parse(&field.attrs)?; - 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 needs_bounds_derive = parsed.needs_bounds_derive::(BoundType::Serialize); + generics + .overrides + .extend(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 { diff --git a/borsh-derive/src/internals/serialize/structs/mod.rs b/borsh-derive/src/internals/serialize/structs/mod.rs index 75dc88893..d364c8a6c 100644 --- a/borsh-derive/src/internals/serialize/structs/mod.rs +++ b/borsh-derive/src/internals/serialize/structs/mod.rs @@ -87,16 +87,10 @@ fn process_field( ) -> syn::Result<()> { let parsed = field::Attributes::parse(&field.attrs)?; - 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 needs_bounds_derive = parsed.needs_bounds_derive::(BoundType::Serialize); + generics + .overrides + .extend(parsed.collect_bounds::(BoundType::Serialize)); if !parsed.skip { let delta = field_id.serialize_output::( From 92316bd6758c3818bde407c35e184090495de6f2 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 16:51:12 +0200 Subject: [PATCH 45/69] Fix doc tests --- borsh/docs/rustdoc_include/borsh_deserialize.md | 11 +++++++++++ borsh/docs/rustdoc_include/borsh_serialize.md | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/borsh/docs/rustdoc_include/borsh_deserialize.md b/borsh/docs/rustdoc_include/borsh_deserialize.md index 0232d661c..b3e22dcfb 100644 --- a/borsh/docs/rustdoc_include/borsh_deserialize.md +++ b/borsh/docs/rustdoc_include/borsh_deserialize.md @@ -109,6 +109,7 @@ This adds a lot of convenience for objects that are architectured to be used as type CryptoHash = String; use borsh::BorshDeserialize; + #[derive(BorshDeserialize)] #[borsh(init=init)] struct Message { @@ -140,6 +141,7 @@ You must specify `use_discriminant` for all enums with explicit discriminants in This is equivalent of borsh version 0.10.3 (explicit discriminant is ignored and this enum is equivalent to `A` without explicit discriminant): ```rust use borsh::BorshDeserialize; + #[derive(BorshDeserialize)] #[borsh(use_discriminant = false)] enum A { @@ -151,6 +153,7 @@ enum A { To have explicit discriminant value serialized as is, you must specify `borsh(use_discriminant=true)` for enum. ```rust use borsh::BorshDeserialize; + #[derive(BorshDeserialize)] #[borsh(use_discriminant = true)] enum B { @@ -165,6 +168,7 @@ This case is not supported: ```rust,compile_fail use borsh::BorshDeserialize; + const fn discrim() -> isize { 0x14 } @@ -186,6 +190,8 @@ enum X { This is not supported: ```rust,compile_fail +use borsh::BorshDeserialize; + #[derive(BorshDeserialize)] #[borsh(use_discriminant = true)] enum X { @@ -211,6 +217,7 @@ parameters encountered in annotated field. ```rust use borsh::BorshDeserialize; + #[derive(BorshDeserialize)] struct A { x: u64, @@ -241,6 +248,7 @@ use hashbrown::HashMap; #[cfg(feature = "std")] use std::collections::HashMap; use core::hash::Hash; + /// additional bounds `T: Ord + Hash + Eq` (required by `HashMap`) are injected into /// derived trait implementation via attribute to avoid adding the bounds on the struct itself #[cfg(any(feature = "hashbrown", feature = "std"))] @@ -259,10 +267,12 @@ struct A { ```rust use borsh::BorshDeserialize; + trait TraitName { type Associated; fn method(&self); } + // derive here figures the bound erroneously as `T: borsh::de::BorshDeserialize,` #[derive(BorshDeserialize)] struct A @@ -286,6 +296,7 @@ use borsh::BorshDeserialize; use hashbrown::HashMap; #[cfg(feature = "std")] use std::collections::HashMap; + /// implicit derived `core::default::Default` bounds on `K` and `V` type parameters are removed by /// empty bound specified, as `HashMap` has its own `Default` implementation #[cfg(any(feature = "hashbrown", feature = "std"))] diff --git a/borsh/docs/rustdoc_include/borsh_serialize.md b/borsh/docs/rustdoc_include/borsh_serialize.md index db87e6865..3f5117898 100644 --- a/borsh/docs/rustdoc_include/borsh_serialize.md +++ b/borsh/docs/rustdoc_include/borsh_serialize.md @@ -125,6 +125,8 @@ enum B { ###### borsh, expressions, evaluating to `isize`, as discriminant This case is not supported: ```rust,compile_fail +use borsh::BorshSerialize; + const fn discrim() -> isize { 0x14 } @@ -144,6 +146,8 @@ enum X { ###### borsh explicit discriminant does not support literal values outside of u8 range This is not supported: ```rust,compile_fail +use borsh::BorshSerialize; + #[derive(BorshSerialize)] #[borsh(use_discriminant = true)] enum X { @@ -192,6 +196,7 @@ use borsh::BorshSerialize; use hashbrown::HashMap; #[cfg(feature = "std")] use std::collections::HashMap; + /// additional bound `T: Ord` (required by `HashMap`) is injected into /// derived trait implementation via attribute to avoid adding the bounds on the struct itself #[cfg(any(feature = "hashbrown", feature = "std"))] @@ -208,10 +213,12 @@ struct A { ```rust use borsh::BorshSerialize; + trait TraitName { type Associated; fn method(&self); } + /// derive here figures the bound erroneously as `T: borsh::ser::BorshSerialize` #[derive(BorshSerialize)] struct A From 1b663e2cb7257ee2a620ce24d02e02d1c5bcb170 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:00:56 +0200 Subject: [PATCH 46/69] Add description for the `unstable__async`, `unstable__tokio` and `unstable__async-std` features --- .../snapshots/both_bounds_parsing-2.snap | 6 ++++++ .../snapshots/both_bounds_parsing-3.snap | 6 ++++++ .../snapshots/both_bounds_parsing-4.snap | 6 ++++++ .../field/snapshots/both_bounds_parsing.snap | 6 ++++++ ...ze_with_skip_conflict_feature_async-2.snap | 7 +++++++ ...lize_with_skip_conflict_feature_async.snap | 7 +++++++ .../snapshots/generic_associated_type-2.snap | 20 +++++++++++++++++++ .../rustdoc_include/borsh_crate_top_level.md | 14 ++++++++++++- 8 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-2.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-3.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-4.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict_feature_async-2.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict_feature_async.snap create mode 100644 borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type-2.snap diff --git a/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-2.snap b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-2.snap new file mode 100644 index 000000000..75ee80942 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-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/both_bounds_parsing-3.snap b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-3.snap new file mode 100644 index 000000000..f7702d582 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-3.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 + A +V : Ord + AA diff --git a/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-4.snap b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-4.snap new file mode 100644 index 000000000..24c22921b --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing-4.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 + A +V : Eq + Ord + AA diff --git a/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing.snap b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing.snap new file mode 100644 index 000000000..182ab0ab3 --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/both_bounds_parsing.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/serialize/structs/snapshots/check_serialize_with_skip_conflict_feature_async-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict_feature_async-2.snap new file mode 100644 index 000000000..3b40ba358 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict_feature_async-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_feature_async.snap b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict_feature_async.snap new file mode 100644 index 000000000..3b40ba358 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/check_serialize_with_skip_conflict_feature_async.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/generic_associated_type-2.snap b/borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type-2.snap new file mode 100644 index 000000000..1adbfacf5 --- /dev/null +++ b/borsh-derive/src/internals/serialize/structs/snapshots/generic_associated_type-2.snap @@ -0,0 +1,20 @@ +--- +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::Associated: 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> { + ::serialize(&self.field, writer) + .await?; + ::serialize(&self.another, writer).await?; + ::core::result::Result::Ok(()) + } +} diff --git a/borsh/docs/rustdoc_include/borsh_crate_top_level.md b/borsh/docs/rustdoc_include/borsh_crate_top_level.md index 29624c193..78bb33a93 100644 --- a/borsh/docs/rustdoc_include/borsh_crate_top_level.md +++ b/borsh/docs/rustdoc_include/borsh_crate_top_level.md @@ -22,11 +22,23 @@ * **derive** - Gates derive macros of [BorshSerialize] and - [BorshDeserialize] traits. + [BorshDeserialize] traits, as well as of [BorshSchema], + [BorshAsyncSerialize] and [BorshAsyncDeserialize] traits + if corresponding features are enabled. * **unstable__schema** - Gates [BorshSchema] trait and its derive macro. Gates [schema] module. This feature requires **derive** to be enabled too. +* **unstable__async** - + Gates [BorshAsyncSerialize] and [BorshAsyncDeserialize] traits. + Gates [async_io] module. + This feature is meant to allow implementing serialization/deserialization + using async I/O. +* **unstable__tokio** / **unstable__async-std** - + Gates implementation of [async_io::AsyncWrite] and [async_io::AsyncRead] + for `tokio` and `async-std` runtimes respectively. + Enabling either of these features will also enable **unstable__async** feature. + These features are set to be mutually exclusive. * **rc** - Gates implementation of [BorshSerialize] and [BorshDeserialize] for [`Rc`](std::rc::Rc)/[`Arc`](std::sync::Arc) respectively. From fb1e01dddb95a0b913bf4a00c9ded24a8803fc46 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:27:04 +0200 Subject: [PATCH 47/69] guard async-related code under the `async` feature flag --- borsh-derive/Cargo.toml | 2 + .../src/internals/attributes/field/mod.rs | 154 +++++++++++++++--- .../src/internals/attributes/item/mod.rs | 14 +- borsh-derive/src/internals/attributes/mod.rs | 13 +- .../src/internals/deserialize/enums/mod.rs | 93 ++++++++--- borsh-derive/src/internals/deserialize/mod.rs | 9 +- .../src/internals/deserialize/structs/mod.rs | 94 ++++++++--- .../src/internals/serialize/enums/mod.rs | 116 +++++++++---- .../src/internals/serialize/structs/mod.rs | 127 ++++++++++++--- .../check_serialize_with_skip_conflict.snap | 2 +- borsh-derive/src/lib.rs | 2 + borsh/Cargo.toml | 4 +- 12 files changed, 477 insertions(+), 153 deletions(-) diff --git a/borsh-derive/Cargo.toml b/borsh-derive/Cargo.toml index 4596d6d42..d9dfa80b0 100644 --- a/borsh-derive/Cargo.toml +++ b/borsh-derive/Cargo.toml @@ -23,6 +23,7 @@ proc-macro-crate = "3" proc-macro2 = "1.0" quote = "1.0" once_cell = "1.18.0" +cfg-if = "1.0" [dev-dependencies] syn = { version = "2.0.96", features = ["parsing"] } @@ -36,5 +37,6 @@ targets = ["x86_64-unknown-linux-gnu"] [features] default = [] +async = [] schema = [] force_exhaustive_checks = [] diff --git a/borsh-derive/src/internals/attributes/field/mod.rs b/borsh-derive/src/internals/attributes/field/mod.rs index f7c4d74df..390088acc 100644 --- a/borsh-derive/src/internals/attributes/field/mod.rs +++ b/borsh-derive/src/internals/attributes/field/mod.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; +use cfg_if::cfg_if; use once_cell::sync::Lazy; use syn::{meta::ParseNestedMeta, Attribute, WherePredicate}; #[cfg(feature = "schema")] @@ -12,9 +13,10 @@ 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, ASYNC_BOUND, BORSH, BOUND, DESERIALIZE_WITH, DESERIALIZE_WITH_ASYNC, - SERIALIZE_WITH, SERIALIZE_WITH_ASYNC, SKIP, + BoundType, Symbol, BORSH, BOUND, DESERIALIZE_WITH, SERIALIZE_WITH, SKIP, }; +#[cfg(feature = "async")] +use super::{ASYNC_BOUND, DESERIALIZE_WITH_ASYNC, SERIALIZE_WITH_ASYNC}; pub mod bounds; #[cfg(feature = "schema")] @@ -43,6 +45,7 @@ static BORSH_FIELD_PARSE_MAP: Lazy>> = Lazy::new(| Ok(Variants::Bounds(bounds_attributes)) }); + #[cfg(feature = "async")] 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(); @@ -59,11 +62,13 @@ static BORSH_FIELD_PARSE_MAP: Lazy>> = Lazy::new(| .map(Variants::DeserializeWith) }); + #[cfg(feature = "async")] 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) }); + #[cfg(feature = "async")] 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) @@ -79,10 +84,13 @@ 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); + #[cfg(feature = "async")] m.insert(ASYNC_BOUND, f_async_bounds); m.insert(SERIALIZE_WITH, f_serialize_with); m.insert(DESERIALIZE_WITH, f_deserialize_with); + #[cfg(feature = "async")] m.insert(SERIALIZE_WITH_ASYNC, f_serialize_with_async); + #[cfg(feature = "async")] m.insert(DESERIALIZE_WITH_ASYNC, f_deserialize_with_async); m.insert(SKIP, f_skip); #[cfg(feature = "schema")] @@ -93,10 +101,13 @@ static BORSH_FIELD_PARSE_MAP: Lazy>> = Lazy::new(| #[derive(Default, Clone)] pub(crate) struct Attributes { pub bounds: Option, + #[cfg(feature = "async")] pub async_bounds: Option, pub serialize_with: Option, pub deserialize_with: Option, + #[cfg(feature = "async")] pub serialize_with_async: Option, + #[cfg(feature = "async")] pub deserialize_with_async: Option, pub skip: bool, #[cfg(feature = "schema")] @@ -106,10 +117,13 @@ pub(crate) struct Attributes { impl From> for Attributes { fn from(mut map: BTreeMap) -> Self { let bounds = map.remove(&BOUND); + #[cfg(feature = "async")] let async_bounds = map.remove(&ASYNC_BOUND); let serialize_with = map.remove(&SERIALIZE_WITH); let deserialize_with = map.remove(&DESERIALIZE_WITH); + #[cfg(feature = "async")] let serialize_with_async = map.remove(&SERIALIZE_WITH_ASYNC); + #[cfg(feature = "async")] let deserialize_with_async = map.remove(&DESERIALIZE_WITH_ASYNC); let skip = map.remove(&SKIP); @@ -118,6 +132,7 @@ impl From> for Attributes { _ => unreachable!("only one enum variant is expected to correspond to given map key"), }); + #[cfg(feature = "async")] 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"), @@ -133,11 +148,13 @@ impl From> for Attributes { _ => unreachable!("only one enum variant is expected to correspond to given map key"), }); + #[cfg(feature = "async")] 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"), }); + #[cfg(feature = "async")] 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"), @@ -161,10 +178,13 @@ impl From> for Attributes { Self { bounds, + #[cfg(feature = "async")] async_bounds, serialize_with, deserialize_with, + #[cfg(feature = "async")] serialize_with_async, + #[cfg(feature = "async")] deserialize_with_async, skip: skip.is_some(), #[cfg(feature = "schema")] @@ -182,23 +202,42 @@ 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() - || 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.name, - SERIALIZE_WITH.name, - DESERIALIZE_WITH.name, - SERIALIZE_WITH_ASYNC.name, - DESERIALIZE_WITH_ASYNC.name - ), - )); + cfg_if! { + if #[cfg(feature = "async")] { + let test_serde_with = || + self.serialize_with.is_some() || + self.deserialize_with.is_some() || + self.serialize_with_async.is_some() || + self.deserialize_with_async.is_some(); + } else { + let test_serde_with = || + self.serialize_with.is_some() || + self.deserialize_with.is_some(); + } + } + + if self.skip && test_serde_with() { + cfg_if! { + if #[cfg(feature = "async")] { + let msg = format!( + "`{}` 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, + ); + } else { + let msg = format!( + "`{}` cannot be used at the same time as `{}` or `{}`", + SKIP.name, + SERIALIZE_WITH.name, + DESERIALIZE_WITH.name, + ); + } + } + + return Err(syn::Error::new_spanned(attr, msg)); } #[cfg(feature = "schema")] @@ -227,14 +266,27 @@ impl Attributes { } fn get_bounds(&self, ty: BoundType) -> Option> { - let bounds = if IS_ASYNC { self.async_bounds.as_ref() } else { self.bounds.as_ref() }; + let bounds = if IS_ASYNC { + cfg_if! { + if #[cfg(feature = "async")] { + self.async_bounds.as_ref() + } else { + None + } + } + } else { + self.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 { + pub(crate) fn collect_bounds( + &self, + ty: BoundType, + ) -> Vec { let predicates = self.get_bounds::(ty); predicates.unwrap_or_default() } @@ -306,7 +358,8 @@ mod tests { }; struct ParsedBounds { - common: Option, + sync: Option, + #[cfg(feature = "async")] r#async: Option, } @@ -314,7 +367,8 @@ mod tests { // #[borsh(bound(serialize = "...", deserialize = "..."), async_bound(serialize = "...", deserialize = "..."))] let borsh_attrs = Attributes::parse(attrs)?; Ok(ParsedBounds { - common: borsh_attrs.bounds, + sync: borsh_attrs.bounds, + #[cfg(feature = "async")] r#async: borsh_attrs.async_bounds, }) } @@ -357,7 +411,7 @@ mod tests { }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); + let attrs = parse_bounds(&first_field.attrs).unwrap().sync.unwrap(); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize)); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } @@ -377,7 +431,7 @@ mod tests { }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); + let attrs = parse_bounds(&first_field.attrs).unwrap().sync.unwrap(); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize)); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } @@ -396,7 +450,7 @@ mod tests { }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); + let attrs = parse_bounds(&first_field.attrs).unwrap().sync.unwrap(); assert_eq!(attrs.serialize.as_ref().unwrap().len(), 0); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } @@ -412,7 +466,7 @@ mod tests { }; let first_field = &item_struct.fields.into_iter().collect::>()[0]; - let attrs = parse_bounds(&first_field.attrs).unwrap().common.unwrap(); + let attrs = parse_bounds(&first_field.attrs).unwrap().sync.unwrap(); assert!(attrs.serialize.is_none()); local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); } @@ -472,6 +526,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_bounds_parsing1() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -495,6 +550,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_bounds_parsing2() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -517,6 +573,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_bounds_parsing3() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -537,6 +594,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_bounds_parsing4() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -553,6 +611,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_bounds_parsing_error() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -571,6 +630,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_bounds_parsing_error2() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -589,6 +649,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_bounds_parsing_error3() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -606,6 +667,44 @@ mod tests { local_insta_assert_debug_snapshot!(err); } + #[test] + #[cfg(feature = "async")] + fn test_both_bounds_parsing() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh( + bound( + deserialize = + "K: Hash + Ord, + V: Eq + Ord", + serialize = + "K: Hash + Eq + Ord, + V: Ord" + ), + async_bound( + deserialize = + "K: Hash + Ord + A, + V: Eq + Ord + AA", + serialize = + "K: Hash + Eq + Ord + A, + V: Ord + AA" + ) + )] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let attrs = parse_bounds(&first_field.attrs).unwrap().sync.unwrap(); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.serialize)); + local_insta_assert_snapshot!(debug_print_vec_of_tokenizable(attrs.deserialize)); + + 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_ser_de_with_parsing1() { let item_struct: ItemStruct = parse_quote! { @@ -626,6 +725,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn test_async_ser_de_with_parsing1() { let item_struct: ItemStruct = parse_quote! { struct A { diff --git a/borsh-derive/src/internals/attributes/item/mod.rs b/borsh-derive/src/internals/attributes/item/mod.rs index 8d25d7472..785e6ad05 100644 --- a/borsh-derive/src/internals/attributes/item/mod.rs +++ b/borsh-derive/src/internals/attributes/item/mod.rs @@ -1,16 +1,16 @@ use quote::ToTokens; -use syn::{spanned::Spanned, Attribute, DeriveInput, Error, Expr, ItemEnum, Path}; +use syn::{spanned::Spanned, Attribute, DeriveInput, 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> { +pub fn check_attributes(derive_input: &DeriveInput) -> syn::Result<()> { let borsh = get_one_attribute(&derive_input.attrs)?; if let Some(attr) = borsh { attr.parse_nested_meta(|meta| { if meta.path != USE_DISCRIMINANT && meta.path != INIT && meta.path != CRATE { - return Err(Error::new( + return Err(syn::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) -> syn::Result { if input.variants.len() > 256 { - return Err(Error::new( + return Err(syn::Error::new( input.span(), "up to 256 enum variants are supported", )); @@ -80,7 +80,7 @@ pub(crate) fn contains_use_discriminant(input: &ItemEnum) -> Result Ok(use_discriminant.unwrap_or(false)) } -pub(crate) fn contains_initialize_with(attrs: &[Attribute]) -> Result, Error> { +pub(crate) fn contains_initialize_with(attrs: &[Attribute]) -> syn::Result> { let mut res = None; let attr = attrs.iter().find(|attr| attr.path() == BORSH); if let Some(attr) = attr { @@ -99,7 +99,7 @@ pub(crate) fn contains_initialize_with(attrs: &[Attribute]) -> Result Result, Error> { +pub(crate) fn get_crate(attrs: &[Attribute]) -> syn::Result> { let mut res = None; let attr = attrs.iter().find(|attr| attr.path() == BORSH); if let Some(attr) = attr { diff --git a/borsh-derive/src/internals/attributes/mod.rs b/borsh-derive/src/internals/attributes/mod.rs index a069bc1ec..8b76a7f41 100644 --- a/borsh-derive/src/internals/attributes/mod.rs +++ b/borsh-derive/src/internals/attributes/mod.rs @@ -4,11 +4,11 @@ pub mod field; pub mod item; 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 { + /// Name of the attribute pub name: &'static str, + /// Expected value format representation for error printing pub expected: &'static str, support: AsyncSupport, } @@ -45,8 +45,8 @@ impl Symbol { } } - pub const fn test_support(&self) -> bool { - if IS_ASYNC { + pub const fn test_support(&self) -> bool { + if ASYNC_OR_SYNC_SWITCH { matches!(self.support, AsyncSupport::Async | AsyncSupport::Both) } else { matches!(self.support, AsyncSupport::Sync | AsyncSupport::Both) @@ -57,8 +57,9 @@ impl Symbol { /// `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(...)"); +pub const BOUND: Symbol = Symbol::new_sync("bound", "bound(...)"); /// `async_bound` - sub-borsh nested meta, field-level only; `BorshSerializeAsync` and `BorshDeserializeAsync` contexts +#[cfg(feature = "async")] 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 @@ -77,9 +78,11 @@ pub const SERIALIZE_WITH: Symbol = Symbol::new_sync("serialize_with", "serialize /// `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 +#[cfg(feature = "async")] 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 +#[cfg(feature = "async")] pub const DESERIALIZE_WITH_ASYNC: Symbol = Symbol::new_async("deserialize_with_async", "deserialize_with_async = ..."); /// `crate` - sub-borsh nested meta, item-level only; diff --git a/borsh-derive/src/internals/deserialize/enums/mod.rs b/borsh-derive/src/internals/deserialize/enums/mod.rs index 925d73301..5e5826448 100644 --- a/borsh-derive/src/internals/deserialize/enums/mod.rs +++ b/borsh-derive/src/internals/deserialize/enums/mod.rs @@ -132,8 +132,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -151,8 +154,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -172,8 +178,11 @@ mod tests { let actual = process::(item_enum.clone(), crate_.clone()).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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -191,8 +200,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -210,8 +222,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -229,8 +244,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + 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() { @@ -248,8 +266,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -267,8 +288,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -290,11 +314,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn generic_deserialize_async_bound() { let item_enum: ItemEnum = parse_quote! { enum A { @@ -333,11 +361,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn check_deserialize_with_async_attr() { let item_enum: ItemEnum = parse_quote! { enum C { @@ -374,8 +406,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -395,8 +430,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -416,7 +454,10 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + 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/mod.rs b/borsh-derive/src/internals/deserialize/mod.rs index d544d0ffd..bb79f9c5e 100644 --- a/borsh-derive/src/internals/deserialize/mod.rs +++ b/borsh-derive/src/internals/deserialize/mod.rs @@ -1,3 +1,4 @@ +use cfg_if::cfg_if; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use syn::{parse_quote, ExprPath, Generics, Ident, Path, Type}; @@ -71,7 +72,13 @@ fn process_field( &field.ty, cratename, if IS_ASYNC { - parsed.deserialize_with_async + cfg_if! { + if #[cfg(feature = "async")] { + parsed.deserialize_with_async + } else { + None + } + } } else { parsed.deserialize_with }, diff --git a/borsh-derive/src/internals/deserialize/structs/mod.rs b/borsh-derive/src/internals/deserialize/structs/mod.rs index 759628f76..7ca999d64 100644 --- a/borsh-derive/src/internals/deserialize/structs/mod.rs +++ b/borsh-derive/src/internals/deserialize/structs/mod.rs @@ -97,8 +97,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -115,8 +118,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -131,8 +137,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -144,8 +153,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -160,8 +172,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -176,8 +191,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -193,8 +211,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -210,8 +231,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -227,8 +251,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -247,11 +274,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn generic_deserialize_async_bound() { let item_struct: ItemStruct = parse_quote! { struct C { @@ -284,11 +315,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn test_override_automatically_added_default_trait_async() { let item_struct: ItemStruct = parse_quote! { struct G1( @@ -318,11 +353,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn check_deserialize_with_async_attr() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -352,7 +391,10 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + 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/serialize/enums/mod.rs b/borsh-derive/src/internals/serialize/enums/mod.rs index 76c2ae923..729441d97 100644 --- a/borsh-derive/src/internals/serialize/enums/mod.rs +++ b/borsh-derive/src/internals/serialize/enums/mod.rs @@ -1,3 +1,4 @@ +use cfg_if::cfg_if; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{Fields, Ident, ItemEnum, Lifetime, Path, Token, Variant}; @@ -233,7 +234,13 @@ fn process_field( &field.ty, cratename, if IS_ASYNC { - parsed.serialize_with_async + cfg_if! { + if #[cfg(feature = "async")] { + parsed.serialize_with_async + } else { + None + } + } } else { parsed.serialize_with }, @@ -269,8 +276,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -291,8 +301,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -315,8 +328,11 @@ mod tests { let actual = process::(item_enum.clone(), crate_.clone()).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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -340,8 +356,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -366,8 +385,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -385,8 +407,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -404,8 +429,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -423,8 +451,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -443,8 +474,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -462,8 +496,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -485,11 +522,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn generic_serialize_async_bound() { let item_enum: ItemEnum = parse_quote! { enum A { @@ -528,11 +569,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn check_serialize_with_async_attr() { let item_enum: ItemEnum = parse_quote! { enum C { @@ -569,8 +614,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] fn borsh_discriminant_true() { @@ -589,8 +637,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_enum, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -607,7 +658,10 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + 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/structs/mod.rs b/borsh-derive/src/internals/serialize/structs/mod.rs index d364c8a6c..add3a767f 100644 --- a/borsh-derive/src/internals/serialize/structs/mod.rs +++ b/borsh-derive/src/internals/serialize/structs/mod.rs @@ -1,3 +1,4 @@ +use cfg_if::cfg_if; use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; use quote::quote; use syn::{Fields, ItemStruct, Lifetime, Path, Token}; @@ -97,7 +98,13 @@ fn process_field( &field.ty, cratename, if IS_ASYNC { - parsed.serialize_with_async + cfg_if! { + if #[cfg(feature = "async")] { + parsed.serialize_with_async + } else { + None + } + } } else { parsed.serialize_with }, @@ -133,8 +140,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -151,8 +161,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, crate_).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -167,8 +180,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -180,8 +196,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -196,8 +215,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -212,8 +234,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -229,8 +254,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -246,8 +274,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -263,8 +294,11 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -279,9 +313,14 @@ mod tests { } }; - 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()); + + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] @@ -300,11 +339,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn generic_serialize_async_bound() { let item_struct: ItemStruct = parse_quote! { struct C { @@ -339,11 +382,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn async_override_generic_associated_type_wrong_derive() { let item_struct: ItemStruct = parse_quote! { struct Parametrized where T: TraitName { @@ -375,11 +422,15 @@ mod tests { 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()); + #[cfg(feature = "async")] + { + let actual = process::(item_struct, default_cratename()).unwrap(); + local_insta_assert_snapshot!(pretty_print_syn_str(actual).unwrap()); + } } #[test] + #[cfg(feature = "async")] fn check_serialize_with_async_attr() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -397,6 +448,7 @@ mod tests { } #[test] + #[cfg(not(feature = "async"))] fn check_serialize_with_skip_conflict() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -413,6 +465,26 @@ mod tests { Err(err) => err, }; local_insta_assert_debug_snapshot!(err); + } + + #[test] + #[cfg(feature = "async")] + fn check_serialize_with_skip_conflict_feature_async() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(skip, serialize_with = "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()); @@ -424,6 +496,7 @@ mod tests { } #[test] + #[cfg(feature = "async")] fn check_serialize_with_async_skip_conflict() { let item_struct: ItemStruct = parse_quote! { struct A { 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 3b40ba358..0334d44bb 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`, `deserialize_with`, `serialize_with_async` or `deserialize_with_async`", + "`skip` cannot be used at the same time as `serialize_with` or `deserialize_with`", ) diff --git a/borsh-derive/src/lib.rs b/borsh-derive/src/lib.rs index 6f6ae501c..ee409fc78 100644 --- a/borsh-derive/src/lib.rs +++ b/borsh-derive/src/lib.rs @@ -41,6 +41,7 @@ pub fn borsh_serialize(input: TokenStream) -> TokenStream { /// --- /// /// moved to docs of **Derive Macro** `BorshSerializeAsync` in `borsh` crate +#[cfg(feature = "async")] #[proc_macro_derive(BorshSerializeAsync, attributes(borsh))] pub fn borsh_serialize_async(input: TokenStream) -> TokenStream { borsh_serialize_generic::(input) @@ -78,6 +79,7 @@ pub fn borsh_deserialize(input: TokenStream) -> TokenStream { /// --- /// /// moved to docs of **Derive Macro** `BorshDeserializeAsync` in `borsh` crate +#[cfg(feature = "async")] #[proc_macro_derive(BorshDeserializeAsync, attributes(borsh))] pub fn borsh_deserialize_async(input: TokenStream) -> TokenStream { borsh_deserialize_generic::(input) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 4e9353746..b539e7428 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -56,8 +56,8 @@ targets = ["x86_64-unknown-linux-gnu"] [features] default = ["std"] -derive = ["borsh-derive"] -unstable__async = [] +derive = ["dep:borsh-derive"] +unstable__async = ["borsh-derive?/async"] unstable__tokio = ["unstable__async", "dep:tokio", "std"] unstable__async-std = ["unstable__async", "dep:async-std", "std"] unstable__schema = ["derive", "borsh-derive/schema"] From f842c46fd76be52561fa5433912fdf1fcfb2aa5d Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:28:18 +0200 Subject: [PATCH 48/69] add docs on IO --- borsh/src/async_io.rs | 130 +++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index 66e2d3a78..6729f1aea 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -1,15 +1,21 @@ use core::future::Future; -use crate::io::Result; - +use crate::io::Result as BorshIoResult; + +/// Asynchronous read trait. +/// +/// `read_` methods imply little-endian byte order, +/// otherwise it's incorrect in the context of `borsh`. +/// +/// Blanked implementations for `tokio` and `async-std` are provided. pub trait AsyncRead: Unpin + Send { fn read<'a>(&'a mut self, buf: &'a mut [u8]) - -> impl Future> + Send + 'a; + -> impl Future> + Send + 'a; fn read_exact<'a>( &'a mut self, buf: &'a mut [u8], - ) -> impl Future> + Send + 'a { + ) -> impl Future> + Send + 'a { async { let mut offset = 0; while offset < buf.len() { @@ -26,7 +32,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u8(&mut self) -> impl Future> + Send { + fn read_u8(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 1]; self.read_exact(&mut buf).await?; @@ -34,7 +40,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u16(&mut self) -> impl Future> + Send { + fn read_u16(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 2]; self.read_exact(&mut buf).await?; @@ -42,7 +48,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u32(&mut self) -> impl Future> + Send { + fn read_u32(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 4]; self.read_exact(&mut buf).await?; @@ -50,7 +56,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u64(&mut self) -> impl Future> + Send { + fn read_u64(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 8]; self.read_exact(&mut buf).await?; @@ -58,7 +64,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_u128(&mut self) -> impl Future> + Send { + fn read_u128(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 16]; self.read_exact(&mut buf).await?; @@ -66,7 +72,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i8(&mut self) -> impl Future> + Send { + fn read_i8(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 1]; self.read_exact(&mut buf).await?; @@ -74,7 +80,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i16(&mut self) -> impl Future> + Send { + fn read_i16(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 2]; self.read_exact(&mut buf).await?; @@ -82,7 +88,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i32(&mut self) -> impl Future> + Send { + fn read_i32(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 4]; self.read_exact(&mut buf).await?; @@ -90,7 +96,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i64(&mut self) -> impl Future> + Send { + fn read_i64(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 8]; self.read_exact(&mut buf).await?; @@ -98,7 +104,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_i128(&mut self) -> impl Future> + Send { + fn read_i128(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 16]; self.read_exact(&mut buf).await?; @@ -106,7 +112,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_f32(&mut self) -> impl Future> + Send { + fn read_f32(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 4]; self.read_exact(&mut buf).await?; @@ -114,7 +120,7 @@ pub trait AsyncRead: Unpin + Send { } } - fn read_f64(&mut self) -> impl Future> + Send { + fn read_f64(&mut self) -> impl Future> + Send { async { let mut buf = [0u8; 8]; self.read_exact(&mut buf).await?; @@ -129,74 +135,74 @@ impl AsyncRead for R { fn read<'a>( &'a mut self, buf: &'a mut [u8], - ) -> impl Future> + Send + 'a { + ) -> impl Future> + Send + 'a { tokio::io::AsyncReadExt::read(self, buf) } #[inline] - async fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> Result<()> { + async fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> BorshIoResult<()> { tokio::io::AsyncReadExt::read_exact(self, buf) .await .map(|_| ()) } #[inline] - fn read_u8(&mut self) -> impl Future> + Send { + fn read_u8(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u8(self) } #[inline] - fn read_u16(&mut self) -> impl Future> + Send { + fn read_u16(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u16_le(self) } #[inline] - fn read_u32(&mut self) -> impl Future> + Send { + fn read_u32(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u32_le(self) } #[inline] - fn read_u64(&mut self) -> impl Future> + Send { + fn read_u64(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u64_le(self) } #[inline] - fn read_u128(&mut self) -> impl Future> + Send { + fn read_u128(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_u128_le(self) } #[inline] - fn read_i8(&mut self) -> impl Future> + Send { + fn read_i8(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i8(self) } #[inline] - fn read_i16(&mut self) -> impl Future> + Send { + fn read_i16(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i16_le(self) } #[inline] - fn read_i32(&mut self) -> impl Future> + Send { + fn read_i32(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i32_le(self) } #[inline] - fn read_i64(&mut self) -> impl Future> + Send { + fn read_i64(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i64_le(self) } #[inline] - fn read_i128(&mut self) -> impl Future> + Send { + fn read_i128(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_i128_le(self) } #[inline] - fn read_f32(&mut self) -> impl Future> + Send { + fn read_f32(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_f32_le(self) } #[inline] - fn read_f64(&mut self) -> impl Future> + Send { + fn read_f64(&mut self) -> impl Future> + Send { tokio::io::AsyncReadExt::read_f64_le(self) } } @@ -207,7 +213,7 @@ impl AsyncRead for R { fn read<'a>( &'a mut self, buf: &'a mut [u8], - ) -> impl Future> + Send + 'a { + ) -> impl Future> + Send + 'a { async_std::io::ReadExt::read(self, buf) } @@ -215,15 +221,21 @@ impl AsyncRead for R { fn read_exact<'a>( &'a mut self, buf: &'a mut [u8], - ) -> impl Future> + Send + 'a { + ) -> impl Future> + Send + 'a { async_std::io::ReadExt::read_exact(self, buf) } } +/// Asynchronous write trait. +/// +/// `write_` methods imply little-endian byte order, +/// otherwise it's incorrect in the context of `borsh`. +/// +/// Blanked implementations for `tokio` and `async-std` are provided. pub trait AsyncWrite: Unpin + Send { - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a; + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a; - fn write_u8(&mut self, n: u8) -> impl Future> + Send { + fn write_u8(&mut self, n: u8) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -231,7 +243,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u16(&mut self, n: u16) -> impl Future> + Send { + fn write_u16(&mut self, n: u16) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -239,7 +251,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u32(&mut self, n: u32) -> impl Future> + Send { + fn write_u32(&mut self, n: u32) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -247,7 +259,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u64(&mut self, n: u64) -> impl Future> + Send { + fn write_u64(&mut self, n: u64) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -255,7 +267,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_u128(&mut self, n: u128) -> impl Future> + Send { + fn write_u128(&mut self, n: u128) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -263,7 +275,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i8(&mut self, n: i8) -> impl Future> + Send { + fn write_i8(&mut self, n: i8) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -271,7 +283,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i16(&mut self, n: i16) -> impl Future> + Send { + fn write_i16(&mut self, n: i16) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -279,7 +291,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i32(&mut self, n: i32) -> impl Future> + Send { + fn write_i32(&mut self, n: i32) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -287,7 +299,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i64(&mut self, n: i64) -> impl Future> + Send { + fn write_i64(&mut self, n: i64) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -295,7 +307,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_i128(&mut self, n: i128) -> impl Future> + Send { + fn write_i128(&mut self, n: i128) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -303,7 +315,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_f32(&mut self, n: f32) -> impl Future> + Send { + fn write_f32(&mut self, n: f32) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -311,7 +323,7 @@ pub trait AsyncWrite: Unpin + Send { } } - fn write_f64(&mut self, n: f64) -> impl Future> + Send { + fn write_f64(&mut self, n: f64) -> impl Future> + Send { async move { let bytes = n.to_le_bytes(); self.write_all(&bytes).await?; @@ -323,67 +335,67 @@ pub trait AsyncWrite: Unpin + Send { #[cfg(feature = "unstable__tokio")] impl AsyncWrite for R { #[inline] - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_all(self, buf) } #[inline] - fn write_u8(&mut self, n: u8) -> impl Future> + Send { + fn write_u8(&mut self, n: u8) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u8(self, n) } #[inline] - fn write_u16(&mut self, n: u16) -> impl Future> + Send { + fn write_u16(&mut self, n: u16) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u16_le(self, n) } #[inline] - fn write_u32(&mut self, n: u32) -> impl Future> + Send { + fn write_u32(&mut self, n: u32) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u32_le(self, n) } #[inline] - fn write_u64(&mut self, n: u64) -> impl Future> + Send { + fn write_u64(&mut self, n: u64) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u64_le(self, n) } #[inline] - fn write_u128(&mut self, n: u128) -> impl Future> + Send { + fn write_u128(&mut self, n: u128) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_u128_le(self, n) } #[inline] - fn write_i8(&mut self, n: i8) -> impl Future> + Send { + fn write_i8(&mut self, n: i8) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i8(self, n) } #[inline] - fn write_i16(&mut self, n: i16) -> impl Future> + Send { + fn write_i16(&mut self, n: i16) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i16_le(self, n) } #[inline] - fn write_i32(&mut self, n: i32) -> impl Future> + Send { + fn write_i32(&mut self, n: i32) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i32_le(self, n) } #[inline] - fn write_i64(&mut self, n: i64) -> impl Future> + Send { + fn write_i64(&mut self, n: i64) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i64_le(self, n) } #[inline] - fn write_i128(&mut self, n: i128) -> impl Future> + Send { + fn write_i128(&mut self, n: i128) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_i128_le(self, n) } #[inline] - fn write_f32(&mut self, n: f32) -> impl Future> + Send { + fn write_f32(&mut self, n: f32) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_f32_le(self, n) } #[inline] - fn write_f64(&mut self, n: f64) -> impl Future> + Send { + fn write_f64(&mut self, n: f64) -> impl Future> + Send { tokio::io::AsyncWriteExt::write_f64_le(self, n) } } @@ -391,7 +403,7 @@ impl AsyncWrite for R { #[cfg(feature = "unstable__async-std")] impl AsyncWrite for R { #[inline] - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { + fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { async_std::io::WriteExt::write_all(self, buf) } } From a7296958266b9f47301cb134747aacf0d2d4ec4f Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:29:05 +0200 Subject: [PATCH 49/69] Fix tests in CI --- .github/test.sh | 1 + .github/workflows/rust.yml | 2 +- borsh/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/test.sh b/.github/test.sh index 6fea5344c..351a87912 100755 --- a/.github/test.sh +++ b/.github/test.sh @@ -17,6 +17,7 @@ cargo test cargo test --features derive cargo test --features derive,unstable__tokio cargo test --features derive,unstable__async-std +cargo test --features derive,unstable__async 'compile_derives::async_derives' cargo test --features unstable__schema ########## features = ["ascii"] group cargo test --features ascii 'roundtrip::test_ascii_strings' diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 428f7c1d1..d1997122d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -82,7 +82,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: run cargo doc - run: RUSTDOCFLAGS="-D warnings" cargo doc --features derive,unstable__schema + run: RUSTDOCFLAGS="-D warnings" cargo doc --features derive,unstable__schema,unstable__async release-plz: runs-on: ubuntu-latest diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index b539e7428..ee29f3248 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -51,7 +51,7 @@ insta = "1.29.0" serde_json = { version = "1" } [package.metadata.docs.rs] -features = ["derive", "unstable__schema", "rc"] +features = ["derive", "unstable__schema", "rc", "unsteble__async"] targets = ["x86_64-unknown-linux-gnu"] [features] From 49cf09638c17862bfa0e95279e8b85cdb38884c5 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:29:34 +0200 Subject: [PATCH 50/69] Fix benchmarks features --- benchmarks/Cargo.toml | 5 +- benchmarks/benches/bench.rs | 8 +-- benchmarks/benches/object_length.rs | 4 +- benchmarks/src/lib.rs | 85 +++++++++++++++-------------- 4 files changed, 50 insertions(+), 52 deletions(-) diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index c8d23aac1..241c11d73 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -13,7 +13,7 @@ bench = false [dependencies] rand_xorshift = "0.2.0" rand = "0.7.0" -borsh = { path = "../borsh", default-features = false } +borsh = { path = "../borsh", default-features = false, features = ["std", "derive"] } serde = { version = "1.0", features = ["derive"] } speedy-derive = "0.5" speedy = "0.5" @@ -39,6 +39,3 @@ harness = false [[bench]] name = "object_length" harness = false - -[features] -default = ["borsh/std", "borsh/derive"] diff --git a/benchmarks/benches/bench.rs b/benchmarks/benches/bench.rs index 75199bc88..6dde9d754 100644 --- a/benchmarks/benches/bench.rs +++ b/benchmarks/benches/bench.rs @@ -14,8 +14,8 @@ where + BorshDeserialize + SerdeSerialize + SerdeDeserialize<'a> - + Readable<'a, speedy::Endianness> - + Writable + + Readable<'a, Endianness> + + Writable + 'static, { let mut rng = rand_xorshift::XorShiftRng::from_seed([0u8; 16]); @@ -71,8 +71,8 @@ where + BorshDeserialize + SerdeSerialize + SerdeDeserialize<'a> - + Readable<'a, speedy::Endianness> - + Writable + + Readable<'a, Endianness> + + Writable + 'static, { let mut rng = rand_xorshift::XorShiftRng::from_seed([0u8; 16]); diff --git a/benchmarks/benches/object_length.rs b/benchmarks/benches/object_length.rs index e69e62a78..ca83b3f38 100644 --- a/benchmarks/benches/object_length.rs +++ b/benchmarks/benches/object_length.rs @@ -1,5 +1,5 @@ use benchmarks::{Generate, ValidatorStake}; -use borsh::{to_vec, BorshSerialize}; +use borsh::BorshSerialize; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use rand::SeedableRng; @@ -11,7 +11,7 @@ where let mut group = c.benchmark_group(group_name); let objects: Vec<_> = (0..num_samples).map(|_| T::generate(&mut rng)).collect(); - let borsh_datas: Vec> = objects.iter().map(|t| to_vec(t).unwrap()).collect(); + let borsh_datas: Vec> = objects.iter().map(|t| borsh::to_vec(t).unwrap()).collect(); let borsh_sizes: Vec<_> = borsh_datas.iter().map(|d| d.len()).collect(); for i in 0..objects.len() { diff --git a/benchmarks/src/lib.rs b/benchmarks/src/lib.rs index 36474ba76..35a8e8d21 100644 --- a/benchmarks/src/lib.rs +++ b/benchmarks/src/lib.rs @@ -1,14 +1,15 @@ //! This library contains data structures used for benchmarking. +extern crate speedy_derive; + use borsh::{BorshDeserialize, BorshSerialize}; use rand::distributions::{Alphanumeric, Distribution, Standard}; use rand::Rng; use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize}; -extern crate speedy_derive; use speedy::{Context, Readable, Reader, Writable, Writer}; pub trait Generate { - fn generate(rng: &mut R) -> Self; + fn generate(rng: &mut R) -> Self; } #[derive( @@ -16,7 +17,7 @@ pub trait Generate { )] pub struct CryptoHash([u8; 32]); impl Generate for CryptoHash { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { let mut res = [0u8; 32]; rng.fill_bytes(&mut res); CryptoHash(res) @@ -27,7 +28,7 @@ impl<'a, C> Readable<'a, C> for CryptoHash where C: Context, { - fn read_from>(reader: &mut R) -> std::result::Result { + fn read_from>(reader: &mut R) -> Result { let mut data = [0u8; 32]; reader.read_bytes(&mut data)?; Ok(Self(data)) @@ -38,7 +39,7 @@ impl Writable for CryptoHash { fn write_to<'a, T: ?Sized + Writer<'a, C>>( &'a self, writer: &mut T, - ) -> std::result::Result<(), std::io::Error> { + ) -> Result<(), std::io::Error> { writer.write_bytes(&self.0).map(|_| ()) } } @@ -48,7 +49,7 @@ impl Writable for CryptoHash { )] pub struct MerkleHash([u8; 32]); impl Generate for MerkleHash { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { let mut res = [0u8; 32]; rng.fill_bytes(&mut res); MerkleHash(res) @@ -59,7 +60,7 @@ impl<'a, C> Readable<'a, C> for MerkleHash where C: Context, { - fn read_from>(reader: &mut R) -> std::result::Result { + fn read_from>(reader: &mut R) -> Result { let mut data = [0u8; 32]; reader.read_bytes(&mut data)?; Ok(Self(data)) @@ -70,7 +71,7 @@ impl Writable for MerkleHash { fn write_to<'a, T: ?Sized + Writer<'a, C>>( &'a self, writer: &mut T, - ) -> std::result::Result<(), std::io::Error> { + ) -> Result<(), std::io::Error> { writer.write_bytes(&self.0).map(|_| ()) } } @@ -80,7 +81,7 @@ impl Writable for MerkleHash { )] pub struct Signature([u8; 32]); impl Generate for Signature { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { let mut res = [0u8; 32]; rng.fill_bytes(&mut res); Signature(res) @@ -91,7 +92,7 @@ impl<'a, C> Readable<'a, C> for Signature where C: Context, { - fn read_from>(reader: &mut R) -> std::result::Result { + fn read_from>(reader: &mut R) -> Result { let mut data = [0u8; 32]; reader.read_bytes(&mut data)?; Ok(Self(data)) @@ -102,7 +103,7 @@ impl Writable for Signature { fn write_to<'a, T: ?Sized + Writer<'a, C>>( &'a self, writer: &mut T, - ) -> std::result::Result<(), std::io::Error> { + ) -> Result<(), std::io::Error> { writer.write_bytes(&self.0).map(|_| ()) } } @@ -122,7 +123,7 @@ impl Writable for Signature { )] pub struct PublicKey([u8; 32]); impl Generate for PublicKey { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { let mut res = [0u8; 32]; rng.fill_bytes(&mut res); PublicKey(res) @@ -130,7 +131,7 @@ impl Generate for PublicKey { } impl Generate for (PublicKey, PublicKey) { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { (PublicKey::generate(rng), PublicKey::generate(rng)) } } @@ -139,7 +140,7 @@ impl<'a, C> Readable<'a, C> for PublicKey where C: Context, { - fn read_from>(reader: &mut R) -> std::result::Result { + fn read_from>(reader: &mut R) -> Result { let mut data = [0u8; 32]; reader.read_bytes(&mut data)?; Ok(Self(data)) @@ -150,7 +151,7 @@ impl Writable for PublicKey { fn write_to<'a, T: ?Sized + Writer<'a, C>>( &'a self, writer: &mut T, - ) -> std::result::Result<(), std::io::Error> { + ) -> Result<(), std::io::Error> { writer.write_bytes(&self.0).map(|_| ()) } } @@ -169,20 +170,20 @@ impl Writable for PublicKey { )] pub struct AccountId(String); impl Generate for String { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { let len: usize = rng.gen_range(5, 200); rng.sample_iter(&Alphanumeric).take(len).collect::() } } impl Generate for (String, String) { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { (String::generate(rng), String::generate(rng)) } } impl Generate for AccountId { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { AccountId(String::generate(rng)) } } @@ -208,7 +209,7 @@ pub struct ValidatorStake { } impl Generate for ValidatorStake { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { account_id: AccountId::generate(rng), public_key: PublicKey::generate(rng), @@ -223,7 +224,7 @@ pub type Weight = u64; pub fn generate_vec_primitives(rng: &mut R, min_number: usize, max_number: usize) -> Vec where Standard: Distribution, - R: rand::Rng, + R: Rng, { let num: usize = rng.gen_range(min_number, max_number + 1); let mut res = vec![]; @@ -233,7 +234,7 @@ where res } -pub fn generate_vec( +pub fn generate_vec( rng: &mut R, min_number: usize, max_number: usize, @@ -272,7 +273,7 @@ pub struct BlockHeaderInner { } impl Generate for BlockHeaderInner { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { height: u64::generate(rng), epoch_hash: CryptoHash::generate(rng), @@ -307,7 +308,7 @@ pub struct BlockHeader { } impl Generate for BlockHeader { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { inner: BlockHeaderInner::generate(rng), signature: Signature::generate(rng), @@ -334,7 +335,7 @@ pub struct Block { } impl Generate for Block { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { header: BlockHeader::generate(rng), transactions: generate_vec(rng, 0, 1000), @@ -361,7 +362,7 @@ pub struct SignedTransaction { } impl Generate for SignedTransaction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { transaction: Transaction::generate(rng), signature: Signature::generate(rng), @@ -393,7 +394,7 @@ pub struct Transaction { } impl Generate for Transaction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { signer_id: AccountId::generate(rng), public_key: PublicKey::generate(rng), @@ -428,7 +429,7 @@ pub enum Action { } impl Generate for Action { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { use Action::*; // Deploy contract action is 1000 times less frequent than other actions. if u64::generate(rng) % 1000 == 0 { @@ -462,7 +463,7 @@ impl Generate for Action { )] pub struct CreateAccountAction {} impl Generate for CreateAccountAction { - fn generate(_rng: &mut R) -> Self { + fn generate(_rng: &mut R) -> Self { Self {} } } @@ -483,7 +484,7 @@ pub struct DeployContractAction { code: Vec, } -pub fn generate_vec_u8(rng: &mut R, min_number: usize, max_number: usize) -> Vec { +pub fn generate_vec_u8(rng: &mut R, min_number: usize, max_number: usize) -> Vec { let num: usize = rng.gen_range(min_number, max_number + 1); let mut res = vec![0u8; num]; rng.fill_bytes(&mut res); @@ -491,7 +492,7 @@ pub fn generate_vec_u8(rng: &mut R, min_number: usize, max_number: } impl Generate for DeployContractAction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { // Between 20KiB and 1MiB. code: generate_vec_u8(rng, 20 * 2usize.pow(10), 2usize.pow(20)), @@ -521,7 +522,7 @@ pub struct FunctionCallAction { } impl Generate for FunctionCallAction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { method_name: String::generate(rng), args: generate_vec_u8(rng, 0, 1000), @@ -546,7 +547,7 @@ pub struct TransferAction { deposit: Balance, } impl Generate for TransferAction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { deposit: u64::generate(rng), } @@ -571,7 +572,7 @@ pub struct StakeAction { } impl Generate for StakeAction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { stake: u64::generate(rng), public_key: PublicKey::generate(rng), @@ -597,7 +598,7 @@ pub struct AddKeyAction { } impl Generate for AddKeyAction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { public_key: PublicKey::generate(rng), access_key: AccessKey::generate(rng), @@ -622,7 +623,7 @@ pub struct DeleteKeyAction { } impl Generate for DeleteKeyAction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { public_key: PublicKey::generate(rng), } @@ -646,7 +647,7 @@ pub struct DeleteAccountAction { } impl Generate for DeleteAccountAction { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { beneficiary_id: AccountId::generate(rng), } @@ -671,7 +672,7 @@ pub struct AccessKey { } impl Generate for AccessKey { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { nonce: u64::generate(rng), permission: AccessKeyPermission::generate(rng), @@ -697,7 +698,7 @@ pub enum AccessKeyPermission { } impl Generate for AccessKeyPermission { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { if u64::generate(rng) % 2 == 0 { AccessKeyPermission::FunctionCall(FunctionCallPermission::generate(rng)) } else { @@ -724,7 +725,7 @@ pub struct FunctionCallPermission { method_names: Vec, } -fn generate_option(rng: &mut R) -> Option { +fn generate_option(rng: &mut R) -> Option { if u64::generate(rng) % 2 == 0 { None } else { @@ -733,13 +734,13 @@ fn generate_option(rng: &mut R) -> Option { } impl Generate for u64 { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { rng.next_u64() } } impl Generate for FunctionCallPermission { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { allowance: generate_option(rng), receiver_id: AccountId::generate(rng), @@ -769,7 +770,7 @@ pub struct Account { } impl Generate for Account { - fn generate(rng: &mut R) -> Self { + fn generate(rng: &mut R) -> Self { Self { amount: u64::generate(rng), staked: u64::generate(rng), From b669baf751d91403bdbad783d9680d8807e93500 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:33:10 +0200 Subject: [PATCH 51/69] Fix clippy warnings --- borsh-derive/src/internals/attributes/field/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/borsh-derive/src/internals/attributes/field/mod.rs b/borsh-derive/src/internals/attributes/field/mod.rs index 390088acc..615d836f7 100644 --- a/borsh-derive/src/internals/attributes/field/mod.rs +++ b/borsh-derive/src/internals/attributes/field/mod.rs @@ -26,7 +26,9 @@ enum Variants { Bounds(bounds::Bounds), SerializeWith(syn::ExprPath), DeserializeWith(syn::ExprPath), + #[cfg(feature = "async")] SerializeWithAsync(syn::ExprPath), + #[cfg(feature = "async")] DeserializeWithAsync(syn::ExprPath), Skip(()), #[cfg(feature = "schema")] From c5b99e51e54c6139c2007f1b0acdeb0397f8100a Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:33:36 +0200 Subject: [PATCH 52/69] fmt --- borsh/src/async_io.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/borsh/src/async_io.rs b/borsh/src/async_io.rs index 6729f1aea..a0c45235e 100644 --- a/borsh/src/async_io.rs +++ b/borsh/src/async_io.rs @@ -3,14 +3,16 @@ use core::future::Future; use crate::io::Result as BorshIoResult; /// Asynchronous read trait. -/// +/// /// `read_` methods imply little-endian byte order, /// otherwise it's incorrect in the context of `borsh`. -/// +/// /// Blanked implementations for `tokio` and `async-std` are provided. pub trait AsyncRead: Unpin + Send { - fn read<'a>(&'a mut self, buf: &'a mut [u8]) - -> impl Future> + Send + 'a; + fn read<'a>( + &'a mut self, + buf: &'a mut [u8], + ) -> impl Future> + Send + 'a; fn read_exact<'a>( &'a mut self, @@ -227,13 +229,16 @@ impl AsyncRead for R { } /// Asynchronous write trait. -/// +/// /// `write_` methods imply little-endian byte order, /// otherwise it's incorrect in the context of `borsh`. -/// +/// /// Blanked implementations for `tokio` and `async-std` are provided. pub trait AsyncWrite: Unpin + Send { - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a; + fn write_all<'a>( + &'a mut self, + buf: &'a [u8], + ) -> impl Future> + Send + 'a; fn write_u8(&mut self, n: u8) -> impl Future> + Send { async move { @@ -335,7 +340,10 @@ pub trait AsyncWrite: Unpin + Send { #[cfg(feature = "unstable__tokio")] impl AsyncWrite for R { #[inline] - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { + fn write_all<'a>( + &'a mut self, + buf: &'a [u8], + ) -> impl Future> + Send + 'a { tokio::io::AsyncWriteExt::write_all(self, buf) } @@ -403,7 +411,10 @@ impl AsyncWrite for R { #[cfg(feature = "unstable__async-std")] impl AsyncWrite for R { #[inline] - fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + Send + 'a { + fn write_all<'a>( + &'a mut self, + buf: &'a [u8], + ) -> impl Future> + Send + 'a { async_std::io::WriteExt::write_all(self, buf) } } From 9f4c5e3f8b2612af9b8baf5548fb040db9d50267 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 17:34:32 +0200 Subject: [PATCH 53/69] Fix doc links --- borsh/docs/rustdoc_include/borsh_crate_top_level.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/borsh/docs/rustdoc_include/borsh_crate_top_level.md b/borsh/docs/rustdoc_include/borsh_crate_top_level.md index 78bb33a93..cd6a79e1e 100644 --- a/borsh/docs/rustdoc_include/borsh_crate_top_level.md +++ b/borsh/docs/rustdoc_include/borsh_crate_top_level.md @@ -23,14 +23,14 @@ * **derive** - Gates derive macros of [BorshSerialize] and [BorshDeserialize] traits, as well as of [BorshSchema], - [BorshAsyncSerialize] and [BorshAsyncDeserialize] traits + [BorshSerializeAsync] and [BorshDeserializeAsync] traits if corresponding features are enabled. * **unstable__schema** - Gates [BorshSchema] trait and its derive macro. Gates [schema] module. This feature requires **derive** to be enabled too. * **unstable__async** - - Gates [BorshAsyncSerialize] and [BorshAsyncDeserialize] traits. + Gates [BorshSerializeAsync] and [BorshDeserializeAsync] traits. Gates [async_io] module. This feature is meant to allow implementing serialization/deserialization using async I/O. From f23ed33f6c9d3adc608cf0688936a4fcc28900ac Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 18:53:53 +0200 Subject: [PATCH 54/69] Use monospace for types and features --- .../rustdoc_include/borsh_crate_top_level.md | 90 ++++++++++--------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/borsh/docs/rustdoc_include/borsh_crate_top_level.md b/borsh/docs/rustdoc_include/borsh_crate_top_level.md index cd6a79e1e..ef7b2946c 100644 --- a/borsh/docs/rustdoc_include/borsh_crate_top_level.md +++ b/borsh/docs/rustdoc_include/borsh_crate_top_level.md @@ -7,12 +7,12 @@ result in building the crate in `no_std` environment. To carter such builds, Borsh offers [`io`] module which includes a items which - are used in [`BorshSerialize`] and [`BorshDeserialize`] traits. Most notably + are used in [`BorshSerialize`] and [`BorshDeserialize`] traits. Most notably `io::Read`, `io::Write` and `io::Result`. When **std** feature is enabled, those items are re-exports of corresponding - `std::io` items. Otherwise they are borsh-specific types which mimic - behaviour of corresponding standard types. + `std::io` items. Otherwise they are borsh-specific types which mimic + behavior of corresponding standard types. ### Default features @@ -20,65 +20,67 @@ ### Other features -* **derive** - - Gates derive macros of [BorshSerialize] and - [BorshDeserialize] traits, as well as of [BorshSchema], - [BorshSerializeAsync] and [BorshDeserializeAsync] traits +* **`derive`** - + Gates derive macros of [`BorshSerialize`] and + [`BorshDeserialize`] traits, as well as of [`BorshSchema`], + [`BorshSerializeAsync`] and [`BorshDeserializeAsync`] traits if corresponding features are enabled. -* **unstable__schema** - - Gates [BorshSchema] trait and its derive macro. - Gates [schema] module. - This feature requires **derive** to be enabled too. -* **unstable__async** - - Gates [BorshSerializeAsync] and [BorshDeserializeAsync] traits. - Gates [async_io] module. +* **`unstable__schema`** - + Gates [`BorshSchema`] trait and its derive macro. + Gates [`schema`] module. + This feature requires **`derive`** to be enabled too. +* **`unstable__async`** - + Gates [`BorshSerializeAsync`] and [`BorshDeserializeAsync`] traits. + Gates [`async_io`] module. This feature is meant to allow implementing serialization/deserialization using async I/O. -* **unstable__tokio** / **unstable__async-std** - - Gates implementation of [async_io::AsyncWrite] and [async_io::AsyncRead] +* **`unstable__tokio`** / **`unstable__async-std`** - + Gates implementation of [`async_io::AsyncWrite`] and [`async_io::AsyncRead`] for `tokio` and `async-std` runtimes respectively. - Enabling either of these features will also enable **unstable__async** feature. + Enabling either of these features will also enable **`unstable__async`** feature. These features are set to be mutually exclusive. -* **rc** - - Gates implementation of [BorshSerialize] and [BorshDeserialize] +* **`rc`** - + Gates implementation of [`BorshSerialize`] and [`BorshDeserialize`] for [`Rc`](std::rc::Rc)/[`Arc`](std::sync::Arc) respectively. In `no_std` setting `Rc`/`Arc` are pulled from `alloc` crate. Serializing and deserializing these types does not preserve identity and may result in multiple copies of the same data. Be sure that this is what you want before enabling this feature. -* **hashbrown** - - Pulls in [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet) when no `std` is available. - This feature is set to be mutually exclusive with **std** feature. -* **bytes** - - Gates implementation of [BorshSerialize] and [BorshDeserialize] - for [Bytes](https://docs.rs/bytes/1.5.0/bytes/struct.Bytes.html) and [BytesMut](https://docs.rs/bytes/1.5.0/bytes/struct.BytesMut.html). -* **bson** - - Gates implementation of [BorshSerialize] and [BorshDeserialize] - for [ObjectId](https://docs.rs/bson/2.9.0/bson/oid/struct.ObjectId.html). -* **ascii** - - Gates implementation of [BorshSerialize], [BorshDeserialize], [BorshSchema] for - types from [ascii](https://docs.rs/ascii/1.1.0/ascii/) crate. -* **de_strict_order** - +* **`hashbrown`** - + Pulls in [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet) when no `std` is available. + This feature is set to be mutually exclusive with **`std`** feature. +* **`bytes`** - + Gates implementation of [`BorshSerialize`] and [`BorshDeserialize`] + for [`Bytes`](https://docs.rs/bytes/1.5.0/bytes/struct.Bytes.html) and [ + `BytesMut`](https://docs.rs/bytes/1.5.0/bytes/struct.BytesMut.html). +* **`bson`** - + Gates implementation of [`BorshSerialize`] and [`BorshDeserialize`] + for [`ObjectId`](https://docs.rs/bson/2.9.0/bson/oid/struct.ObjectId.html). +* **`ascii`** - + Gates implementation of [`BorshSerialize`], [`BorshDeserialize`], [`BorshSchema`] for + types from [`ascii`](https://docs.rs/ascii/1.1.0/ascii/) crate. +* **`de_strict_order`** - Enables check that keys, parsed during deserialization of - [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet) and - [BTreeSet](std::collections::BTreeSet)/[BTreeMap](std::collections::BTreeMap) - are encountered in ascending order with respect to [PartialOrd] for hash collections, - and [Ord] for btree ones. Deserialization emits error otherwise. + [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet) and + [`BTreeSet`](std::collections::BTreeSet)/[`BTreeMap`](std::collections::BTreeMap) + are encountered in ascending order with respect to [`PartialOrd`] for hash collections, + and [`Ord`] for btree ones. + Deserialization emits error otherwise. - If this feature is not enabled, it is possible that two different byte slices could deserialize into the same `HashMap`/`HashSet` object. + If this feature is not enabled, it is possible that two different byte slices could deserialize into the same + [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet) object. ### Config aliases -* **hash_collections** - - This is a feature alias, set up in `build.rs` to be equivalent to (**std** OR **hashbrown**). - Gates implementation of [BorshSerialize], [BorshDeserialize] - and [BorshSchema] - for [HashMap](std::collections::HashMap)/[HashSet](std::collections::HashSet). +* **`hash_collections`** - + This is a feature alias, set up in `build.rs` to be equivalent to (**`std`** OR **`hashbrown`**). + Gates implementation of [`BorshSerialize`], [`BorshDeserialize`] + and [`BorshSchema`] + for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). # Shortcuts -Following pages are highlighted here just to give reader a chance at learning that -they exist. +Following pages are highlighted here just to give reader a chance at learning that they exist. - [Derive Macro `BorshSerialize`](macro@crate::BorshSerialize) - [Derive Macro `BorshDeserialize`](macro@crate::BorshDeserialize) From 57a0a40778142aa873241ebe2dac519acb182aa3 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 18:59:23 +0200 Subject: [PATCH 55/69] Fix tests --- .../src/internals/attributes/field/mod.rs | 43 +++++++++++++++++++ .../root_bounds_and_wrong_key_combined.snap | 2 +- ..._and_wrong_key_combined_feature_async.snap | 7 +++ .../field/snapshots/root_error.snap | 2 +- .../snapshots/root_error_feature_async.snap | 7 +++ 5 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined_feature_async.snap create mode 100644 borsh-derive/src/internals/attributes/field/snapshots/root_error_feature_async.snap diff --git a/borsh-derive/src/internals/attributes/field/mod.rs b/borsh-derive/src/internals/attributes/field/mod.rs index 615d836f7..1d93ba68e 100644 --- a/borsh-derive/src/internals/attributes/field/mod.rs +++ b/borsh-derive/src/internals/attributes/field/mod.rs @@ -991,6 +991,7 @@ mod tests_schema { } #[test] + #[cfg(not(feature = "async"))] fn test_root_error() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -1009,6 +1010,26 @@ mod tests_schema { } #[test] + #[cfg(feature = "async")] + fn test_root_error_feature_async() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(boons)] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + let err = match Attributes::parse(&first_field.attrs) { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); + } + + #[test] + #[cfg(not(feature = "async"))] fn test_root_bounds_and_wrong_key_combined() { let item_struct: ItemStruct = parse_quote! { struct A { @@ -1028,4 +1049,26 @@ mod tests_schema { }; local_insta_assert_debug_snapshot!(err); } + + #[test] + #[cfg(feature = "async")] + fn test_root_bounds_and_wrong_key_combined_feature_async() { + let item_struct: ItemStruct = parse_quote! { + struct A { + #[borsh(bound(deserialize = "K: Hash"), + schhema(params = "T => ::Associated, V => Vec") + )] + x: u64, + y: String, + } + }; + + let first_field = &item_struct.fields.into_iter().collect::>()[0]; + + let err = match Attributes::parse(&first_field.attrs) { + Ok(..) => unreachable!("expecting error here"), + Err(err) => err, + }; + local_insta_assert_debug_snapshot!(err); + } } 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 f62d0826e..110f4f29f 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(async_bound(...), bound(...), deserialize_with = ..., deserialize_with_async = ..., schema(...), serialize_with = ..., serialize_with_async = ..., skip)`", + "malformed borsh attribute, expected `borsh(bound(...), deserialize_with = ..., schema(...), serialize_with = ..., skip)`", ) diff --git a/borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined_feature_async.snap b/borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined_feature_async.snap new file mode 100644 index 000000000..f62d0826e --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/root_bounds_and_wrong_key_combined_feature_async.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: err +--- +Error( + "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 f62d0826e..110f4f29f 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(async_bound(...), bound(...), deserialize_with = ..., deserialize_with_async = ..., schema(...), serialize_with = ..., serialize_with_async = ..., skip)`", + "malformed borsh attribute, expected `borsh(bound(...), deserialize_with = ..., schema(...), serialize_with = ..., skip)`", ) diff --git a/borsh-derive/src/internals/attributes/field/snapshots/root_error_feature_async.snap b/borsh-derive/src/internals/attributes/field/snapshots/root_error_feature_async.snap new file mode 100644 index 000000000..f62d0826e --- /dev/null +++ b/borsh-derive/src/internals/attributes/field/snapshots/root_error_feature_async.snap @@ -0,0 +1,7 @@ +--- +source: borsh-derive/src/internals/attributes/field/mod.rs +expression: err +--- +Error( + "malformed borsh attribute, expected `borsh(async_bound(...), bound(...), deserialize_with = ..., deserialize_with_async = ..., schema(...), serialize_with = ..., serialize_with_async = ..., skip)`", +) From 584f36fb7192bedd55f11dd1a39a19d78f139c8f Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 19:09:40 +0200 Subject: [PATCH 56/69] Revert changes --- borsh/src/nostd_io.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/borsh/src/nostd_io.rs b/borsh/src/nostd_io.rs index ae87cd536..52061b817 100644 --- a/borsh/src/nostd_io.rs +++ b/borsh/src/nostd_io.rs @@ -1,9 +1,8 @@ //! Taken from https://github.com/bbqsrc/bare-io (with adjustments) +use crate::__private::maybestd::string::String; use core::{convert::From, fmt, result}; -use crate::__private::maybestd::borrow::Cow; - /// A specialized [`Result`] type for I/O operations. /// /// This type is broadly used across [`std::io`] for any operation which may @@ -68,7 +67,7 @@ enum Repr { #[derive(Debug)] struct Custom { kind: ErrorKind, - error: Cow<'static, str>, + error: String, } /// A list specifying general categories of I/O error. @@ -227,15 +226,14 @@ impl Error { /// // errors can also be created from other errors /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); /// ``` - #[inline] - pub fn new>>(kind: ErrorKind, error: T) -> Error { - fn new(kind: ErrorKind, error: Cow<'static, str>) -> Error { - Error { - repr: Repr::Custom(Custom { kind, error }), - } - } + pub fn new>(kind: ErrorKind, error: T) -> Error { + Self::_new(kind, error.into()) + } - new(kind, error.into()) + fn _new(kind: ErrorKind, error: String) -> Error { + Error { + repr: Repr::Custom(Custom { kind, error }), + } } /// Returns a reference to the inner error wrapped by this error (if any). @@ -299,7 +297,7 @@ impl Error { /// print_error(Error::new(ErrorKind::Other, "oh no!")); /// } /// ``` - pub fn into_inner(self) -> Option> { + pub fn into_inner(self) -> Option { match self.repr { Repr::Simple(..) => None, Repr::Custom(c) => Some(c.error), @@ -651,7 +649,7 @@ impl Write for &mut [u8] { #[inline] fn write(&mut self, data: &[u8]) -> Result { let amt = core::cmp::min(data.len(), self.len()); - let (a, b) = core::mem::take(self).split_at_mut(amt); + let (a, b) = core::mem::replace(self, &mut []).split_at_mut(amt); a.copy_from_slice(&data[..amt]); *self = b; Ok(amt) From bc70f92612626d015ab78e310a9c3e6eb2dc8fd4 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 19:47:34 +0200 Subject: [PATCH 57/69] Add docs to the `async_io` declaration --- borsh/src/lib.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index 18a4250a1..46253e419 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -57,19 +57,24 @@ compile_error!( #[cfg(feature = "std")] use std::io as io_impl; + +/// Module is available if `borsh` is built with `features = ["unstable__async"]`. +/// +/// Provides traits for async I/O operations. #[cfg(feature = "unstable__async")] pub mod async_io; + #[cfg(not(feature = "std"))] mod nostd_io; #[cfg(not(feature = "std"))] use nostd_io as io_impl; -/// Subset of `std::io` which is used as part of borsh public API. +/// Subset of `std::io` which is used as part of `borsh` public API. /// /// When crate is built with `std` feature disabled (it’s enabled by default), -/// the exported types are custom borsh types which try to mimic behaviour of -/// corresponding standard types usually offering subset of features. +/// the exported types are custom `borsh` types that try to mimic the behavior of +/// corresponding standard types, usually offering a subset of features. pub mod io { pub use super::io_impl::{Error, ErrorKind, Read, Result, Write}; } From a5e027e974ff8e254d838af68d643a33639f6f6e Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 19:48:38 +0200 Subject: [PATCH 58/69] Fix lifetimes --- borsh/src/de/mod.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 2d702fa96..33d1fd891 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1654,8 +1654,23 @@ pub fn from_slice(v: &[u8]) -> Result { /// ``` #[async_generic( #[cfg(feature = "unstable__async")] - async_signature[impl_fut]<'a, R: AsyncRead, T: BorshDeserializeAsync + 'a>(reader: &'a mut R) -> impl Future> + Send + 'a + async_signature[impl_fut]( + reader: &mut R, + ) -> impl Future> + Send + Captures<&mut R> )] pub fn from_reader(reader: &mut R) -> Result { T::try_from_reader(reader) } + +use captures::Captures; +mod captures { + /// This is a [trick](https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md#the-captures-trick), + /// used to not over-restrict the lifetime and trait bounds of a RPIT. + /// + /// Once the MSRV is >=1.82, this should be removed and replaced with `use<>` + /// notation for precise capturing. + #[doc(hidden)] + pub trait Captures {} + + impl Captures for U {} +} \ No newline at end of file From 018c35684bd7f87fa444479be3a91d16f29d89ee Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 19:49:28 +0200 Subject: [PATCH 59/69] fmt --- borsh/src/de/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 33d1fd891..e8cfee2ff 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1673,4 +1673,4 @@ mod captures { pub trait Captures {} impl Captures for U {} -} \ No newline at end of file +} From 19e1571b7dd5e877a5c100e08d45a3564dee321b Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 19:50:35 +0200 Subject: [PATCH 60/69] Fix clippy & fmt warnings --- borsh/src/de/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index e8cfee2ff..7ece93b62 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1662,7 +1662,9 @@ pub fn from_reader(reader: &mut R) -> Result { T::try_from_reader(reader) } +#[cfg(feature = "unstable__async")] use captures::Captures; +#[cfg(feature = "unstable__async")] mod captures { /// This is a [trick](https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md#the-captures-trick), /// used to not over-restrict the lifetime and trait bounds of a RPIT. From 66447cbf5f48e8ddc2f7749177d10f0fc2862601 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 20:31:28 +0200 Subject: [PATCH 61/69] Fix docs and doc tests --- borsh/Cargo.toml | 1 + .../rustdoc_include/borsh_crate_top_level.md | 2 + borsh/src/de/mod.rs | 64 +++++++++++++------ borsh/src/lib.rs | 4 +- borsh/src/ser/helpers.rs | 13 +++- 5 files changed, 60 insertions(+), 24 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index ee29f3248..8c68e51a8 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -47,6 +47,7 @@ async-std = { version = "1", default-features = false, features = ["std"], optio [dev-dependencies] tokio-test = "0.4.4" +tokio = { version = "1", features = ["io-std"] } insta = "1.29.0" serde_json = { version = "1" } diff --git a/borsh/docs/rustdoc_include/borsh_crate_top_level.md b/borsh/docs/rustdoc_include/borsh_crate_top_level.md index ef7b2946c..e4e35d82b 100644 --- a/borsh/docs/rustdoc_include/borsh_crate_top_level.md +++ b/borsh/docs/rustdoc_include/borsh_crate_top_level.md @@ -85,4 +85,6 @@ Following pages are highlighted here just to give reader a chance at learning th - [Derive Macro `BorshSerialize`](macro@crate::BorshSerialize) - [Derive Macro `BorshDeserialize`](macro@crate::BorshDeserialize) - [Derive Macro `BorshSchema`](macro@crate::BorshSchema) +- [Derive Macro `BorshSerializeAsync`](macro@crate::BorshSerializeAsync) +- [Derive Macro `BorshDeserializeAsync`](macro@crate::BorshDeserializeAsync) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 7ece93b62..01cfefd33 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1632,27 +1632,51 @@ pub fn from_slice(v: &[u8]) -> Result { /// Deserializes an object from a reader. /// # Example -/// ``` -/// use borsh::{BorshDeserialize, BorshSerialize, from_reader, to_vec}; -/// -/// /// derive is only available if borsh is built with `features = ["derive"]` -/// # #[cfg(feature = "derive")] -/// #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] -/// struct MyStruct { -/// a: u64, -/// b: Vec, -/// } -/// -/// # #[cfg(feature = "derive")] -/// let original = MyStruct { a: 10, b: vec![1, 2, 3] }; -/// # #[cfg(feature = "derive")] -/// let encoded = to_vec(&original).unwrap(); -/// # #[cfg(feature = "derive")] -/// let decoded = from_reader::<_, MyStruct>(&mut encoded.as_slice()).unwrap(); -/// # #[cfg(feature = "derive")] -/// assert_eq!(original, decoded); -/// ``` #[async_generic( + /// ``` + /// use borsh::{BorshDeserialize, BorshSerialize, from_reader, to_vec}; + /// + /// /// derive is only available if borsh is built with `features = ["derive"]` + /// # #[cfg(feature = "derive")] + /// #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] + /// struct MyStruct { + /// a: u64, + /// b: Vec, + /// } + /// + /// # #[cfg(feature = "derive")] + /// let original = MyStruct { a: 10, b: vec![1, 2, 3] }; + /// # #[cfg(feature = "derive")] + /// let encoded = to_vec(&original).unwrap(); + /// # #[cfg(feature = "derive")] + /// let decoded = from_reader::<_, MyStruct>(&mut encoded.as_slice()).unwrap(); + /// # #[cfg(feature = "derive")] + /// assert_eq!(original, decoded); + /// ``` + sync_signature; + + /// ``` + /// use borsh::{BorshDeserializeAsync, BorshSerialize, from_reader_async, to_vec}; + /// + /// /// derive is only available if borsh is built with `features = ["derive"]` + /// # #[cfg(feature = "derive")] + /// #[derive(BorshSerialize, BorshDeserializeAsync, PartialEq, Debug)] + /// struct MyStruct { + /// a: u64, + /// b: Vec, + /// } + /// + /// # tokio_test::block_on(async { + /// # #[cfg(feature = "derive")] + /// let original = MyStruct { a: 10, b: vec![1, 2, 3] }; + /// # #[cfg(feature = "derive")] + /// let encoded = to_vec(&original).unwrap(); + /// # #[cfg(feature = "derive")] + /// let decoded = from_reader_async::<_, MyStruct>(&mut encoded.as_slice()).await.unwrap(); + /// # #[cfg(feature = "derive")] + /// assert_eq!(original, decoded); + /// # }); + /// ``` #[cfg(feature = "unstable__async")] async_signature[impl_fut]( reader: &mut R, diff --git a/borsh/src/lib.rs b/borsh/src/lib.rs index 46253e419..84069bec2 100644 --- a/borsh/src/lib.rs +++ b/borsh/src/lib.rs @@ -58,9 +58,9 @@ compile_error!( #[cfg(feature = "std")] use std::io as io_impl; -/// Module is available if `borsh` is built with `features = ["unstable__async"]`. -/// /// Provides traits for async I/O operations. +/// +/// Module is available if `borsh` is built with `features = ["unstable__async"]`. #[cfg(feature = "unstable__async")] pub mod async_io; diff --git a/borsh/src/ser/helpers.rs b/borsh/src/ser/helpers.rs index 58ed90d32..4375ce1d6 100644 --- a/borsh/src/ser/helpers.rs +++ b/borsh/src/ser/helpers.rs @@ -26,16 +26,25 @@ where } /// Serializes an object directly into a `Writer`. -/// # Example /// +/// # Example #[async_generic( /// ``` /// # #[cfg(feature = "std")] /// let stderr = std::io::stderr(); /// # #[cfg(feature = "std")] - /// assert_eq!((), borsh::to_writer(&stderr, "hello_0x0a").unwrap()); + /// borsh::to_writer(&stderr, "hello_0x0a").unwrap(); /// ``` sync_signature; + + /// ``` + /// # tokio_test::block_on(async { + /// # #[cfg(feature = "unstable__tokio")] + /// let mut stderr = tokio::io::stderr(); + /// # #[cfg(feature = "unstable__tokio")] + /// borsh::to_writer_async(&mut stderr, "hello_0x0a").await.unwrap(); + /// # }) + /// ``` #[cfg(feature = "unstable__async")] async_signature(mut writer: W, value: &T) -> Result<()> where From 7c3eb77e1d5117f878c8ecaf7a5d31ada9e19950 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sat, 22 Feb 2025 22:47:21 +0200 Subject: [PATCH 62/69] Fix docs and checks in CI. Fix clippy warnings about mixed attributes. Use more readable async-generic syntax --- .github/workflows/rust.yml | 10 +- borsh/src/de/mod.rs | 275 ++++++++++++++++++++----------------- borsh/src/schema.rs | 13 +- borsh/src/ser/mod.rs | 158 +++++++++++++++------ 4 files changed, 283 insertions(+), 173 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d1997122d..ce3e62532 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -63,7 +63,13 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run clippy - run: cargo clippy --features unstable__schema --benches -- -D clippy::all + run: cargo clippy --features rc,ascii,unstable__schema --benches -- -D clippy::all + - name: Run clippy (async) + run: cargo clippy --features rc,ascii,unstable__schema,unstable__async --benches -- -D clippy::all + - name: Run clippy (tokio) + run: cargo clippy --features rc,ascii,unstable__schema,unstable__tokio --benches -- -D clippy::all + - name: Run clippy (async-std) + run: cargo clippy --features rc,ascii,unstable__schema,unstable__async-std --benches -- -D clippy::all cargo-fmt: runs-on: ubuntu-20.04 @@ -82,7 +88,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: run cargo doc - run: RUSTDOCFLAGS="-D warnings" cargo doc --features derive,unstable__schema,unstable__async + run: RUSTDOCFLAGS="-D warnings" cargo doc --features derive,rc,ascii,unstable__schema,unstable__async release-plz: runs-on: ubuntu-latest diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 01cfefd33..48453dcab 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -192,7 +192,6 @@ pub trait EnumExtAsync: BorshDeserializeAsync { /// variant is being deserialized. /// /// ``` - /// # tokio_test::block_on(async { /// use borsh::BorshDeserializeAsync; /// use borsh::de::EnumExtAsync as _; /// @@ -228,6 +227,7 @@ pub trait EnumExtAsync: BorshDeserializeAsync { /// } /// /// use borsh::from_reader_async; + /// # tokio_test::block_on(async { /// let data = b"\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()); @@ -294,10 +294,11 @@ impl BorshDeserialize for u8 { vec.resize(vec.len().saturating_mul(2).min(len), 0) } // TODO(mina86): Convert this to read_buf once that stabilises. - let res = { - let res = reader.read(&mut vec.as_mut_slice()[pos..]); - if _sync { res } else { res.await }? - }; + let res = if _sync { + reader.read(&mut vec.as_mut_slice()[pos..]) + } else { + reader.read(&mut vec.as_mut_slice()[pos..]).await + }?; match res { 0 => { return Err(Error::new( @@ -320,9 +321,12 @@ impl BorshDeserialize for u8 { )] fn array_from_reader(reader: &mut R) -> Result> { let mut arr = [0u8; N]; - let res = reader.read_exact(&mut arr); - if _sync { res } else { res.await } - .map_err(unexpected_eof_to_unexpected_length_of_input)?; + if _sync { + reader.read_exact(&mut arr) + } else { + reader.read_exact(&mut arr).await + } + .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(Some(arr)) } } @@ -506,10 +510,11 @@ where }?; match flag { 0 => Ok(None), - 1 => Ok(Some({ - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }? - })), + 1 => Ok(Some(if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader(reader).await + }?)), _ => Err(Error::new( ErrorKind::InvalidData, format!( @@ -542,14 +547,16 @@ where ::deserialize_reader(reader).await }?; match flag { - 0 => Ok(Err({ - let res = E::deserialize_reader(reader); - if _sync { res } else { res.await }? - })), - 1 => Ok(Ok({ - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }? - })), + 0 => Ok(Err(if _sync { + E::deserialize_reader(reader) + } else { + E::deserialize_reader(reader).await + }?)), + 1 => Ok(Ok(if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader(reader).await + }?)), _ => Err(Error::new( ErrorKind::InvalidData, format!( @@ -589,13 +596,12 @@ impl BorshDeserialize for String { } /// Module is available if borsh is built with `features = ["ascii"]`. +/// +/// Module defines [`BorshDeserialize`] +#[cfg_attr(feature = "unstable__async", doc = " and [`BorshDeserializeAsync`]")] +/// implementation for some types from [`ascii`](::ascii) crate. #[cfg(feature = "ascii")] pub mod ascii { - //! - //! Module defines [`BorshDeserialize`] - #![cfg_attr(feature = "unstable__async", doc = " & [`BorshDeserializeAsync`]")] - //! implementation for some types from [`ascii`] crate. - use async_generic::async_generic; use super::BorshDeserialize; @@ -684,18 +690,22 @@ where if len == 0 { Ok(Vec::new()) } else if let Some(vec_bytes) = { - let res = T::vec_from_reader(len, reader); - if _sync { res } else { res.await }? + if _sync { + T::vec_from_reader(len, reader) + } else { + T::vec_from_reader(len, reader).await + }? } { Ok(vec_bytes) } else { // TODO(16): return capacity allocation when we can safely do that. let mut result = Vec::with_capacity(hint::cautious::(len)); for _ in 0..len { - result.push({ - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }? - }); + result.push(if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader(reader).await + }?); } Ok(result) } @@ -756,10 +766,11 @@ impl BorshDeserialize for bson::oid::ObjectId { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 12]; - { - let res = reader.read_exact(&mut buf); - if _sync { res } else { res.await }?; - } + if _sync { + reader.read_exact(&mut buf) + } else { + reader.read_exact(&mut buf).await + }?; Ok(bson::oid::ObjectId::from_bytes(buf)) } } @@ -780,10 +791,11 @@ where #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - Ok(Cow::Owned({ - let res = T::Owned::deserialize_reader(reader); - if _sync { res } else { res.await }? - })) + Ok(Cow::Owned(if _sync { + T::Owned::deserialize_reader(reader) + } else { + T::Owned::deserialize_reader(reader).await + }?)) } } @@ -800,10 +812,11 @@ where #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let vec = { - let res = >::deserialize_reader(reader); - if _sync { res } else { res.await }? - }; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader(reader).await + }?; Ok(vec.into()) } } @@ -821,10 +834,11 @@ where #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let vec = { - let res = >::deserialize_reader(reader); - if _sync { res } else { res.await }? - }; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader(reader).await + }?; Ok(vec.into_iter().collect::>()) } } @@ -832,7 +846,7 @@ where /// Module is available if borsh is built with `features = ["std"]` or `features = ["hashbrown"]`. /// /// Module defines [`BorshDeserialize`] -#[cfg_attr(feature = "unstable__async", doc = " & [`BorshDeserializeAsync`]")] +#[cfg_attr(feature = "unstable__async", doc = " and [`BorshDeserializeAsync`]")] /// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { @@ -876,14 +890,14 @@ pub mod hashes { // that it allows to fail early, and not allocate memory for all the elements // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster - let vec = { - let res = >::deserialize_reader(reader); - if _sync { res } else { res.await }? - }; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader(reader).await + }?; #[cfg(feature = "de_strict_order")] - // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 - // TODO: first replace with `array_windows` api when stabilizes https://github.com/rust-lang/rust/issues/75027 + // TODO: replace with `is_sorted` api once MSRV >= 1.82 for pair in vec.windows(2) { let [a, b] = pair else { unreachable!("`windows` always return a slice of length 2 or nothing"); @@ -923,14 +937,14 @@ pub mod hashes { // that it allows to fail early, and not allocate memory for all the entries // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster - let vec = { - let res = >::deserialize_reader(reader); - if _sync { res } else { res.await }? - }; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader(reader).await + }?; #[cfg(feature = "de_strict_order")] - // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 - // TODO: first replace with `array_windows` api when stabilizes https://github.com/rust-lang/rust/issues/75027 + // TODO: replace with `is_sorted` api once MSRV >= 1.82 for pair in vec.windows(2) { let [(a_k, _a_v), (b_k, _b_v)] = pair else { unreachable!("`windows` always return a slice of length 2 or nothing"); @@ -966,14 +980,14 @@ where // that it allows to fail early, and not allocate memory for all the elements // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster - let vec = { - let res = >::deserialize_reader(reader); - if _sync { res } else { res.await }? - }; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader(reader).await + }?; #[cfg(feature = "de_strict_order")] - // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 - // TODO: first replace with `array_windows` api when stabilizes https://github.com/rust-lang/rust/issues/75027 + // TODO: replace with `is_sorted` api once MSRV >= 1.82 for pair in vec.windows(2) { let [a, b] = pair else { unreachable!("`windows` always return a slice of length 2 or nothing"); @@ -1012,14 +1026,14 @@ where // that it allows to fail early, and not allocate memory for all the entries // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster - let vec = { - let res = >::deserialize_reader(reader); - if _sync { res } else { res.await }? - }; + let vec = if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader(reader).await + }?; #[cfg(feature = "de_strict_order")] - // TODO: replace with `is_sorted` api when stabilizes https://github.com/rust-lang/rust/issues/53485 - // TODO: first replace with `array_windows` api when stabilizes https://github.com/rust-lang/rust/issues/75027 + // TODO: replace with `is_sorted` api once MSRV >= 1.82 for pair in vec.windows(2) { let [(a_k, _a_v), (b_k, _b_v)] = pair else { unreachable!("`windows` always return a slice of length 2 or nothing"); @@ -1165,9 +1179,12 @@ impl BorshDeserialize for std::net::Ipv4Addr { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 4]; - let res = reader.read_exact(&mut buf); - if _sync { res } else { res.await } - .map_err(unexpected_eof_to_unexpected_length_of_input)?; + if _sync { + reader.read_exact(&mut buf) + } else { + reader.read_exact(&mut buf).await + } + .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(std::net::Ipv4Addr::from(buf)) } } @@ -1182,9 +1199,12 @@ impl BorshDeserialize for std::net::Ipv6Addr { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 16]; - let res = reader.read_exact(&mut buf); - if _sync { res } else { res.await } - .map_err(unexpected_eof_to_unexpected_length_of_input)?; + if _sync { + reader.read_exact(&mut buf) + } else { + reader.read_exact(&mut buf).await + } + .map_err(unexpected_eof_to_unexpected_length_of_input)?; Ok(std::net::Ipv6Addr::from(buf)) } } @@ -1206,10 +1226,12 @@ where #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - Ok({ - let res = T::Owned::deserialize_reader(reader); - if _sync { res } else { res.await }?.into() - }) + if _sync { + T::Owned::deserialize_reader(reader) + } else { + T::Owned::deserialize_reader(reader).await + } + .map(Into::into) } } @@ -1256,18 +1278,17 @@ where } if let Some(arr) = T::array_from_reader(reader)? { - Ok(arr) - } else { - let mut result = ArrayDropGuard { - buffer: unsafe { MaybeUninit::uninit().assume_init() }, - init_count: 0, - }; + return Ok(arr); + } + let mut result = ArrayDropGuard { + buffer: unsafe { MaybeUninit::uninit().assume_init() }, + init_count: 0, + }; - result.fill_buffer(|| T::deserialize_reader(reader))?; + result.fill_buffer(|| T::deserialize_reader(reader))?; - // SAFETY: The elements up to `i` have been initialized in `fill_buffer`. - Ok(unsafe { result.transmute_to_array() }) - } + // SAFETY: The elements up to `i` have been initialized in `fill_buffer`. + Ok(unsafe { result.transmute_to_array() }) } } @@ -1319,19 +1340,18 @@ where } if let Some(arr) = T::array_from_reader(reader).await? { - Ok(arr) - } else { - let mut result = ArrayDropGuard { - buffer: unsafe { MaybeUninit::uninit().assume_init() }, - init_count: 0, - reader, - }; + return Ok(arr); + } + let mut result = ArrayDropGuard { + buffer: unsafe { MaybeUninit::uninit().assume_init() }, + init_count: 0, + reader, + }; - result.fill_buffer().await?; + result.fill_buffer().await?; - // SAFETY: The elements up to `i` have been initialized in `fill_buffer`. - Ok(unsafe { result.transmute_to_array() }) - } + // SAFETY: The elements up to `i` have been initialized in `fill_buffer`. + Ok(unsafe { result.transmute_to_array() }) } } @@ -1467,10 +1487,11 @@ macro_rules! impl_range { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let [$($side,)*] = { - let res = <[T; $n]>::deserialize_reader(reader); - if _sync { res } else { res.await }? - }; + let [$($side,)*] = if _sync { + <[T; $n]>::deserialize_reader(reader) + } else { + <[T; $n]>::deserialize_reader(reader).await + }?; Ok($make) } } @@ -1484,13 +1505,12 @@ impl_range!(RangeTo, ..end, 1, end); impl_range!(RangeToInclusive, ..=end, 1, end); /// Module is available if borsh is built with `features = ["rc"]`. +/// +/// Module defines [`BorshDeserialize`] +#[cfg_attr(feature = "unstable__async", doc = " and [`BorshDeserializeAsync`]")] +/// implementation for [`alloc::rc::Rc`](std::rc::Rc) and [`alloc::sync::Arc`](std::sync::Arc). #[cfg(feature = "rc")] pub mod rc { - //! - //! Module defines [`BorshDeserialize`] - #![cfg_attr(feature = "unstable__async", doc = " & [`BorshDeserializeAsync`]")] - //! implementation for [`alloc::rc::Rc`](Rc) and [`alloc::sync::Arc`](Arc). - use async_generic::async_generic; use super::BorshDeserialize; @@ -1535,10 +1555,12 @@ pub mod rc { #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - Ok({ - let res = >::deserialize_reader(reader); - if _sync { res } else { res.await }?.into() - }) + if _sync { + >::deserialize_reader(reader) + } else { + >::deserialize_reader(reader).await + } + .map(Into::into) } } } @@ -1570,8 +1592,12 @@ where #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(core::cell::Cell::new) + if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader(reader).await + } + .map(core::cell::Cell::new) } } @@ -1588,8 +1614,12 @@ where #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let res = T::deserialize_reader(reader); - if _sync { res } else { res.await }.map(core::cell::RefCell::new) + if _sync { + T::deserialize_reader(reader) + } else { + T::deserialize_reader(reader).await + } + .map(core::cell::RefCell::new) } } @@ -1692,10 +1722,7 @@ use captures::Captures; mod captures { /// This is a [trick](https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md#the-captures-trick), /// used to not over-restrict the lifetime and trait bounds of a RPIT. - /// - /// Once the MSRV is >=1.82, this should be removed and replaced with `use<>` - /// notation for precise capturing. - #[doc(hidden)] + // TODO: Once the MSRV is >=1.82, this should be removed and replaced with `use<>` notation for precise capturing. pub trait Captures {} impl Captures for U {} diff --git a/borsh/src/schema.rs b/borsh/src/schema.rs index 7d07546b5..6a1589e5a 100644 --- a/borsh/src/schema.rs +++ b/borsh/src/schema.rs @@ -347,12 +347,13 @@ where T::declaration() } } + /// Module is available if borsh is built with `features = ["rc"]`. +/// +/// Module defines [BorshSchema] implementation for +/// [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). #[cfg(feature = "rc")] pub mod rc { - //! - //! Module defines [BorshSchema] implementation for - //! [alloc::rc::Rc](std::rc::Rc) and [alloc::sync::Arc](std::sync::Arc). use super::{Declaration, Definition}; use crate::{ BorshSchema, @@ -485,11 +486,11 @@ impl BorshSchema for str { } /// Module is available if borsh is built with `features = ["ascii"]`. +/// +/// Module defines [BorshSchema] implementation for +/// some types from [ascii](::ascii) crate. #[cfg(feature = "ascii")] pub mod ascii { - //! - //! Module defines [BorshSchema] implementation for - //! some types from [ascii](::ascii) crate. use super::{add_definition, Declaration, Definition}; use crate::{BorshSchema, __private::maybestd::collections::BTreeMap}; diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 72818a58f..27596dc80 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -4,8 +4,6 @@ use core::{convert::TryFrom, marker::PhantomData}; use async_generic::async_generic; -#[cfg(feature = "unstable__async")] -use crate::async_io::AsyncWrite; use crate::{ __private::maybestd::{ borrow::{Cow, ToOwned}, @@ -17,6 +15,8 @@ use crate::{ error::check_zst, io::{Error, ErrorKind, Result, Write}, }; +#[cfg(feature = "unstable__async")] +use crate::async_io::AsyncWrite; pub(crate) mod helpers; @@ -133,7 +133,10 @@ pub trait BorshSerializeAsync: Sync { impl BorshSerialize for u8 { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { @@ -149,6 +152,7 @@ impl BorshSerialize for u8 { } } +#[rustfmt::skip] macro_rules! impl_for_integer { ($type: ident, $method: ident) => { #[async_generic( @@ -158,7 +162,10 @@ macro_rules! impl_for_integer { impl BorshSerialize for $type { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { @@ -182,6 +189,7 @@ impl_for_integer!(u32, write_u32); impl_for_integer!(u64, write_u64); impl_for_integer!(u128, write_u128); +#[rustfmt::skip] macro_rules! impl_for_nonzero_integer { ($type: ty, $method: ident $(, $repr: ty)?) => { #[async_generic( @@ -191,7 +199,10 @@ macro_rules! impl_for_nonzero_integer { impl BorshSerialize for $type { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { @@ -218,6 +229,7 @@ impl_for_nonzero_integer!(core::num::NonZeroU64, write_u64); impl_for_nonzero_integer!(core::num::NonZeroU128, write_u128); impl_for_nonzero_integer!(core::num::NonZeroUsize, write_u64, u64); +#[rustfmt::skip] macro_rules! impl_for_size_integer { ($type:ty: $repr:ty, $method: ident) => { #[async_generic( @@ -227,7 +239,10 @@ macro_rules! impl_for_size_integer { impl BorshSerialize for $type { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { @@ -246,6 +261,7 @@ impl_for_size_integer!(isize: i64, write_i64); // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, // and vice versa. We disallow NaNs to avoid this issue. +#[rustfmt::skip] macro_rules! impl_for_float { ($type: ident, $method: ident) => { #[async_generic( @@ -254,7 +270,9 @@ macro_rules! impl_for_float { )] impl BorshSerialize for $type { #[inline] - #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] + #[async_generic( + async_signature<'a, 'w, W: AsyncWrite>(&'a self, writer: &'w mut W) -> Result<()> + )] fn serialize(&self, writer: &mut W) -> Result<()> { if self.is_nan() { return Err(Error::new(ErrorKind::InvalidData, FLOAT_NAN_ERR)); @@ -280,7 +298,10 @@ impl_for_float!(f64, write_f64); impl BorshSerialize for bool { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let byte = u8::from(*self); @@ -371,7 +392,10 @@ where impl BorshSerialize for str { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_bytes(); @@ -390,7 +414,10 @@ impl BorshSerialize for str { impl BorshSerialize for String { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { @@ -402,13 +429,12 @@ impl BorshSerialize for String { } /// Module is available if borsh is built with `features = ["ascii"]`. +/// +/// Module defines [`BorshSerialize`] +#[cfg_attr(feature = "unstable__async", doc = " and [`BorshSerializeAsync`]")] +/// implementation for some types from [`ascii`](::ascii) crate. #[cfg(feature = "ascii")] pub mod ascii { - //! - //! Module defines [`BorshSerialize`] - #![cfg_attr(feature = "unstable__async", doc = " & [`BorshSerializeAsync`]")] - //! implementation for some types from [`ascii`] crate. - #[cfg(feature = "unstable__async")] use core::future::Future; @@ -426,7 +452,10 @@ pub mod ascii { impl BorshSerialize for ascii::AsciiChar { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let byte = self.as_byte(); @@ -445,7 +474,10 @@ pub mod ascii { impl BorshSerialize for ascii::AsciiStr { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_bytes(); @@ -464,7 +496,10 @@ pub mod ascii { impl BorshSerialize for ascii::AsciiString { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { @@ -532,7 +567,10 @@ where impl BorshSerialize for &T { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { @@ -556,7 +594,10 @@ where { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let r#ref = self.as_ref(); @@ -602,7 +643,10 @@ where impl BorshSerialize for bytes::Bytes { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_ref(); @@ -622,7 +666,10 @@ impl BorshSerialize for bytes::Bytes { impl BorshSerialize for bytes::BytesMut { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let bytes = self.as_ref(); @@ -642,7 +689,10 @@ impl BorshSerialize for bytes::BytesMut { impl BorshSerialize for bson::oid::ObjectId { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { #[inline(always)] @@ -724,13 +774,12 @@ where /// Module is available if borsh is built with `features = ["std"]` or `features = ["hashbrown"]`. /// /// Module defines [`BorshSerialize`] -#[cfg_attr(feature = "unstable__async", doc = " & [`BorshSerializeAsync`]")] +#[cfg_attr(feature = "unstable__async", doc = " and [`BorshSerializeAsync`]")] /// implementation for [`HashMap`](std::collections::HashMap)/[`HashSet`](std::collections::HashSet). #[cfg(hash_collections)] pub mod hashes { - use core::{convert::TryFrom, hash::BuildHasher}; - use async_generic::async_generic; + use core::{convert::TryFrom, hash::BuildHasher}; use super::BorshSerialize; #[cfg(feature = "unstable__async")] @@ -759,7 +808,9 @@ pub mod hashes { H: BuildHasher, { #[inline] - #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] + #[async_generic( + async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -795,7 +846,9 @@ pub mod hashes { H: BuildHasher, { #[inline] - #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] + #[async_generic( + async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> + )] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; @@ -968,7 +1021,10 @@ impl BorshSerialize for std::net::SocketAddrV6 { impl BorshSerialize for std::net::Ipv4Addr { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { #[inline(always)] @@ -994,7 +1050,10 @@ impl BorshSerialize for std::net::Ipv4Addr { impl BorshSerialize for std::net::Ipv6Addr { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { #[inline(always)] @@ -1053,7 +1112,10 @@ impl BorshSerialize for std::net::IpAddr { impl BorshSerialize for Box { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { let r#ref = self.as_ref(); @@ -1099,6 +1161,7 @@ where } } +#[rustfmt::skip] macro_rules! impl_tuple { (@unit $name:ty) => { #[async_generic( @@ -1108,7 +1171,10 @@ macro_rules! impl_tuple { impl BorshSerialize for $name { #[inline] #[async_generic( - async_signature[ready]<'a, W: AsyncWrite>(&'a self, _: &'a mut W) -> impl Future> + Send + 'a + async_signature[ready]<'a, W: AsyncWrite>( + &'a self, + _: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, _: &mut W) -> Result<()> { Ok(()) @@ -1128,7 +1194,9 @@ macro_rules! impl_tuple { $($name: BorshSerialize,)+ { #[inline] - #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] + #[async_generic( + async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> + )] fn serialize(&self, writer: &mut W) -> Result<()> { if _sync { $(BorshSerialize::serialize(&self.$idx, writer)?;)+ @@ -1165,6 +1233,7 @@ impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15 16 T16 17 T17 18 T18); impl_tuple!(0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15 16 T16 17 T17 18 T18 19 T19); +#[rustfmt::skip] macro_rules! impl_range { ($type:ident, $this:ident, $($field:expr),*) => { #[async_generic( @@ -1175,7 +1244,9 @@ macro_rules! impl_range { )] impl BorshSerialize for core::ops::$type { #[inline] - #[async_generic(async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()>)] + #[async_generic( + async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> + )] fn serialize(&self, writer: &mut W) -> Result<()> { let $this = self; if _sync { @@ -1196,13 +1267,12 @@ impl_range!(RangeTo, this, &this.end); impl_range!(RangeToInclusive, this, &this.end); /// Module is available if borsh is built with `features = ["rc"]`. +/// +/// Module defines [`BorshSerialize`] +#[cfg_attr(feature = "unstable__async", doc = " and [`BorshSerializeAsync`]")] +/// implementation for [`alloc::rc::Rc`](std::rc::Rc) and [`alloc::sync::Arc`](std::sync::Arc). #[cfg(feature = "rc")] pub mod rc { - //! - //! Module defines [`BorshSerialize`] - #![cfg_attr(feature = "unstable__async", doc = " & [`BorshSerializeAsync`]")] - //! implementation for [`Rc`] and [`Arc`]. - #[cfg(feature = "unstable__async")] use core::future::Future; @@ -1243,7 +1313,10 @@ pub mod rc { impl BorshSerialize for Arc { #[inline] #[async_generic( - async_signature[impl_fut]<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> impl Future> + Send + 'a + async_signature[impl_fut]<'a, W: AsyncWrite>( + &'a self, + writer: &'a mut W, + ) -> impl Future> + Send + 'a )] fn serialize(&self, writer: &mut W) -> Result<()> { (**self).serialize(writer) @@ -1260,7 +1333,10 @@ pub mod rc { impl BorshSerialize for PhantomData { #[inline] #[async_generic( - async_signature[ready]<'a, W: AsyncWrite>(&'a self, _: &'a mut W) -> impl Future> + Send + async_signature[ready]<'a, W: AsyncWrite>( + &'a self, + _: &'a mut W, + ) -> impl Future> + Send )] fn serialize(&self, _: &mut W) -> Result<()> { Ok(()) From 0a1aab4eae626cd448b9c481f8e316e576e21d82 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sun, 23 Feb 2025 01:08:16 +0200 Subject: [PATCH 63/69] Readability fixes. Add test for async array deserialization --- borsh/Cargo.toml | 2 +- borsh/src/de/mod.rs | 623 +++++++++++++++++++++++++++----------------- 2 files changed, 382 insertions(+), 243 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index 8c68e51a8..cbd964757 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -47,7 +47,7 @@ async-std = { version = "1", default-features = false, features = ["std"], optio [dev-dependencies] tokio-test = "0.4.4" -tokio = { version = "1", features = ["io-std"] } +tokio = { version = "1", features = ["io-std", "macros"] } insta = "1.29.0" serde_json = { version = "1" } diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 48453dcab..cc1f1255f 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -92,11 +92,10 @@ pub trait BorshDeserializeAsync: Sized + Send { fn try_from_reader(reader: &mut R) -> impl Future> + Send { async move { - let result = { Self::deserialize_reader(reader).await }?; + let result = Self::deserialize_reader(reader).await?; let mut buf = [0u8; 1]; - let res = reader.read_exact(&mut buf); - let res = { res.await }; + let res = reader.read_exact(&mut buf).await; match res { Err(f) if f.kind() == ErrorKind::UnexpectedEof => Ok(result), _ => Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)), @@ -295,10 +294,10 @@ impl BorshDeserialize for u8 { } // TODO(mina86): Convert this to read_buf once that stabilises. let res = if _sync { - reader.read(&mut vec.as_mut_slice()[pos..]) + reader.read(&mut vec.as_mut_slice()[pos..])? } else { - reader.read(&mut vec.as_mut_slice()[pos..]).await - }?; + reader.read(&mut vec.as_mut_slice()[pos..]).await? + }; match res { 0 => { return Err(Error::new( @@ -332,59 +331,61 @@ impl BorshDeserialize for u8 { } macro_rules! impl_for_integer { - ($type: ident, $method: ident) => { - #[async_generic( - #[cfg(feature = "unstable__async")] - async_variant - )] + ($type: ident) => { impl BorshDeserialize for $type { - #[inline] - #[async_generic( - async_signature[impl_fut](reader: &mut R) -> impl Future> + Send - )] fn deserialize_reader(reader: &mut R) -> Result { - if _sync { - let mut buf = [0u8; size_of::<$type>()]; - reader - .read_exact(&mut buf) - .map_err(unexpected_eof_to_unexpected_length_of_input)?; - let res = $type::from_le_bytes(buf.try_into().unwrap()); - Ok(res) - } else { - reader.$method() - } + let mut buf = [0u8; size_of::<$type>()]; + reader + .read_exact(&mut buf) + .map_err(unexpected_eof_to_unexpected_length_of_input)?; + let res = $type::from_le_bytes(buf.try_into().unwrap()); + Ok(res) + } + } + }; +} + +impl_for_integer!(i8); +impl_for_integer!(i16); +impl_for_integer!(i32); +impl_for_integer!(i64); +impl_for_integer!(i128); +impl_for_integer!(u16); +impl_for_integer!(u32); +impl_for_integer!(u64); +impl_for_integer!(u128); + +macro_rules! impl_async_for_integer { + ($type: ident, $method: ident) => { + #[cfg(feature = "unstable__async")] + impl BorshDeserializeAsync for $type { + #[inline] + fn deserialize_reader( + reader: &mut R, + ) -> impl Future> + Send { + reader.$method() } } }; } -impl_for_integer!(i8, read_i8); -impl_for_integer!(i16, read_i16); -impl_for_integer!(i32, read_i32); -impl_for_integer!(i64, read_i64); -impl_for_integer!(i128, read_i128); -impl_for_integer!(u16, read_u16); -impl_for_integer!(u32, read_u32); -impl_for_integer!(u64, read_u64); -impl_for_integer!(u128, read_u128); - -#[rustfmt::skip] +impl_async_for_integer!(i8, read_i8); +impl_async_for_integer!(i16, read_i16); +impl_async_for_integer!(i32, read_i32); +impl_async_for_integer!(i64, read_i64); +impl_async_for_integer!(i128, read_i128); +impl_async_for_integer!(u16, read_u16); +impl_async_for_integer!(u32, read_u32); +impl_async_for_integer!(u64, read_u64); +impl_async_for_integer!(u128, read_u128); + macro_rules! impl_for_nonzero_integer { ($type: ty, $repr: ty) => { - #[async_generic( - #[cfg(feature = "unstable__async")] - async_variant - )] impl BorshDeserialize for $type { #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - <$type>::new(if _sync { - <$repr as BorshDeserialize>::deserialize_reader(reader) - } else { - <$repr as BorshDeserializeAsync>::deserialize_reader(reader).await - }?) - .ok_or_else(|| Error::new(ErrorKind::InvalidData, ERROR_INVALID_ZERO_VALUE)) + <$type>::new(<$repr as BorshDeserialize>::deserialize_reader(reader)?) + .ok_or_else(|| Error::new(ErrorKind::InvalidData, ERROR_INVALID_ZERO_VALUE)) } } }; @@ -403,21 +404,38 @@ impl_for_nonzero_integer!(core::num::NonZeroU64, u64); impl_for_nonzero_integer!(core::num::NonZeroU128, u128); impl_for_nonzero_integer!(core::num::NonZeroUsize, usize); -#[rustfmt::skip] +macro_rules! impl_async_for_nonzero_integer { + ($type: ty, $repr: ty) => { + #[cfg(feature = "unstable__async")] + impl BorshDeserializeAsync for $type { + #[inline] + async fn deserialize_reader(reader: &mut R) -> Result { + <$type>::new(<$repr as BorshDeserializeAsync>::deserialize_reader(reader).await?) + .ok_or_else(|| Error::new(ErrorKind::InvalidData, ERROR_INVALID_ZERO_VALUE)) + } + } + }; +} + +impl_async_for_nonzero_integer!(core::num::NonZeroI8, i8); +impl_async_for_nonzero_integer!(core::num::NonZeroI16, i16); +impl_async_for_nonzero_integer!(core::num::NonZeroI32, i32); +impl_async_for_nonzero_integer!(core::num::NonZeroI64, i64); +impl_async_for_nonzero_integer!(core::num::NonZeroI128, i128); +impl_async_for_nonzero_integer!(core::num::NonZeroIsize, isize); +impl_async_for_nonzero_integer!(core::num::NonZeroU8, u8); +impl_async_for_nonzero_integer!(core::num::NonZeroU16, u16); +impl_async_for_nonzero_integer!(core::num::NonZeroU32, u32); +impl_async_for_nonzero_integer!(core::num::NonZeroU64, u64); +impl_async_for_nonzero_integer!(core::num::NonZeroU128, u128); +impl_async_for_nonzero_integer!(core::num::NonZeroUsize, usize); + macro_rules! impl_for_size_integer { ($type: ty: $temp_type: ty, $msg: expr) => { - #[async_generic( - #[cfg(feature = "unstable__async")] - async_variant - )] impl BorshDeserialize for $type { - #[async_generic(async_signature(reader: &mut R) -> Result)] + #[inline] fn deserialize_reader(reader: &mut R) -> Result { - let i = if _sync { - <$temp_type as BorshDeserialize>::deserialize_reader(reader) - } else { - <$temp_type as BorshDeserializeAsync>::deserialize_reader(reader).await - }?; + let i = <$temp_type as BorshDeserialize>::deserialize_reader(reader)?; let i = <$type>::try_from(i).map_err(|_| Error::new(ErrorKind::InvalidData, $msg))?; Ok(i) @@ -429,27 +447,37 @@ macro_rules! impl_for_size_integer { impl_for_size_integer!(isize: i64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_ISIZE); impl_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); +macro_rules! impl_async_for_size_integer { + ($type: ty: $temp_type: ty, $msg: expr) => { + #[cfg(feature = "unstable__async")] + impl BorshDeserializeAsync for $type { + #[inline] + async fn deserialize_reader(reader: &mut R) -> Result { + let i = <$temp_type as BorshDeserializeAsync>::deserialize_reader(reader).await?; + let i = + <$type>::try_from(i).map_err(|_| Error::new(ErrorKind::InvalidData, $msg))?; + Ok(i) + } + } + }; +} + +impl_async_for_size_integer!(isize: i64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_ISIZE); +impl_async_for_size_integer!(usize: u64, ERROR_OVERFLOW_ON_MACHINE_WITH_32_BIT_USIZE); + // Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, // and vice versa. We disallow NaNs to avoid this issue. -#[rustfmt::skip] macro_rules! impl_for_float { - ($type: ident, $int_type: ident, $method: ident) => { - #[async_generic( - #[cfg(feature = "unstable__async")] - async_variant - )] + ($type: ident, $int_type: ident) => { impl BorshDeserialize for $type { #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let res = if _sync { + let res = { let mut buf = [0u8; size_of::<$type>()]; reader .read_exact(&mut buf) .map_err(unexpected_eof_to_unexpected_length_of_input)?; $type::from_bits($int_type::from_le_bytes(buf.try_into().unwrap())) - } else { - reader.$method().await? }; if res.is_nan() { return Err(Error::new( @@ -463,8 +491,32 @@ macro_rules! impl_for_float { }; } -impl_for_float!(f32, u32, read_f32); -impl_for_float!(f64, u64, read_f64); +impl_for_float!(f32, u32); +impl_for_float!(f64, u64); + +// Note NaNs have a portability issue. Specifically, signalling NaNs on MIPS are quiet NaNs on x86, +// and vice versa. We disallow NaNs to avoid this issue. +macro_rules! impl_async_for_float { + ($type: ident, $method: ident) => { + #[cfg(feature = "unstable__async")] + impl BorshDeserializeAsync for $type { + #[inline] + async fn deserialize_reader(reader: &mut R) -> Result { + let res = reader.$method().await?; + if res.is_nan() { + return Err(Error::new( + ErrorKind::InvalidData, + "For portability reasons we do not allow to deserialize NaNs.", + )); + } + Ok(res) + } + } + }; +} + +impl_async_for_float!(f32, read_f32); +impl_async_for_float!(f64, read_f64); #[async_generic( #[cfg(feature = "unstable__async")] @@ -475,10 +527,10 @@ impl BorshDeserialize for bool { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let b = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; match b { 0 => Ok(false), 1 => Ok(true), @@ -504,17 +556,19 @@ where #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let flag = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; match flag { 0 => Ok(None), - 1 => Ok(Some(if _sync { - T::deserialize_reader(reader) - } else { - T::deserialize_reader(reader).await - }?)), + 1 => { + if _sync { + T::deserialize_reader(reader).map(Some) + } else { + T::deserialize_reader(reader).await.map(Some) + } + } _ => Err(Error::new( ErrorKind::InvalidData, format!( @@ -542,21 +596,25 @@ where #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let flag = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; match flag { - 0 => Ok(Err(if _sync { - E::deserialize_reader(reader) - } else { - E::deserialize_reader(reader).await - }?)), - 1 => Ok(Ok(if _sync { - T::deserialize_reader(reader) - } else { - T::deserialize_reader(reader).await - }?)), + 0 => { + if _sync { + E::deserialize_reader(reader).map(Err) + } else { + E::deserialize_reader(reader).await.map(Err) + } + } + 1 => { + if _sync { + T::deserialize_reader(reader).map(Ok) + } else { + T::deserialize_reader(reader).await.map(Ok) + } + } _ => Err(Error::new( ErrorKind::InvalidData, format!( @@ -577,10 +635,10 @@ impl BorshDeserialize for String { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { String::from_utf8(if _sync { - as BorshDeserialize>::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader)? } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await - }?) + as BorshDeserializeAsync>::deserialize_reader(reader).await? + }) .map_err(|err| { #[cfg(feature = "std")] { @@ -621,10 +679,10 @@ pub mod ascii { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let bytes = if _sync { - as BorshDeserialize>::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader)? } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await - }?; + as BorshDeserializeAsync>::deserialize_reader(reader).await? + }; ascii::AsciiString::from_ascii(bytes).map_err(|err| { #[cfg(feature = "std")] { @@ -648,10 +706,10 @@ pub mod ascii { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let byte = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; ascii::AsciiChar::from_ascii(byte).map_err(|err| { #[cfg(feature = "std")] { @@ -683,18 +741,18 @@ where check_zst::()?; let len = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; if len == 0 { Ok(Vec::new()) } else if let Some(vec_bytes) = { if _sync { - T::vec_from_reader(len, reader) + T::vec_from_reader(len, reader)? } else { - T::vec_from_reader(len, reader).await - }? + T::vec_from_reader(len, reader).await? + } } { Ok(vec_bytes) } else { @@ -702,10 +760,10 @@ where let mut result = Vec::with_capacity(hint::cautious::(len)); for _ in 0..len { result.push(if _sync { - T::deserialize_reader(reader) + T::deserialize_reader(reader)? } else { - T::deserialize_reader(reader).await - }?); + T::deserialize_reader(reader).await? + }); } Ok(result) } @@ -722,10 +780,10 @@ impl BorshDeserialize for bytes::Bytes { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { - as BorshDeserialize>::deserialize_reader(reader) + as BorshDeserialize>::deserialize_reader(reader)? } else { - as BorshDeserializeAsync>::deserialize_reader(reader).await - }?; + as BorshDeserializeAsync>::deserialize_reader(reader).await? + }; Ok(vec.into()) } } @@ -740,17 +798,17 @@ impl BorshDeserialize for BytesMut { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let len = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; let mut out = BytesMut::with_capacity(hint::cautious::(len)); for _ in 0..len { out.put_u8(if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?); + ::deserialize_reader(reader).await? + }); } Ok(out) } @@ -767,10 +825,10 @@ impl BorshDeserialize for bson::oid::ObjectId { fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; 12]; if _sync { - reader.read_exact(&mut buf) + reader.read_exact(&mut buf)? } else { - reader.read_exact(&mut buf).await - }?; + reader.read_exact(&mut buf).await? + }; Ok(bson::oid::ObjectId::from_bytes(buf)) } } @@ -792,10 +850,10 @@ where #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { Ok(Cow::Owned(if _sync { - T::Owned::deserialize_reader(reader) + T::Owned::deserialize_reader(reader)? } else { - T::Owned::deserialize_reader(reader).await - }?)) + T::Owned::deserialize_reader(reader).await? + })) } } @@ -812,12 +870,11 @@ where #[inline] #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - let vec = if _sync { - >::deserialize_reader(reader) + if _sync { + >::deserialize_reader(reader).map(Into::into) } else { - >::deserialize_reader(reader).await - }?; - Ok(vec.into()) + >::deserialize_reader(reader).await.map(Into::into) + } } } @@ -835,10 +892,10 @@ where #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let vec = if _sync { - >::deserialize_reader(reader) + >::deserialize_reader(reader)? } else { - >::deserialize_reader(reader).await - }?; + >::deserialize_reader(reader).await? + }; Ok(vec.into_iter().collect::>()) } } @@ -891,10 +948,10 @@ pub mod hashes { // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster let vec = if _sync { - >::deserialize_reader(reader) + >::deserialize_reader(reader)? } else { - >::deserialize_reader(reader).await - }?; + >::deserialize_reader(reader).await? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api once MSRV >= 1.82 @@ -938,10 +995,10 @@ pub mod hashes { // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster let vec = if _sync { - >::deserialize_reader(reader) + >::deserialize_reader(reader)? } else { - >::deserialize_reader(reader).await - }?; + >::deserialize_reader(reader).await? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api once MSRV >= 1.82 @@ -981,10 +1038,10 @@ where // which may fail `cmp()` checks // NOTE: deserialize first to `Vec` is faster let vec = if _sync { - >::deserialize_reader(reader) + >::deserialize_reader(reader)? } else { - >::deserialize_reader(reader).await - }?; + >::deserialize_reader(reader).await? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api once MSRV >= 1.82 @@ -1027,10 +1084,10 @@ where // which may fail `cmp()` checks // NOTE: deserialize first to `Vec<(K, V)>` is faster let vec = if _sync { - >::deserialize_reader(reader) + >::deserialize_reader(reader)? } else { - >::deserialize_reader(reader).await - }?; + >::deserialize_reader(reader).await? + }; #[cfg(feature = "de_strict_order")] // TODO: replace with `is_sorted` api once MSRV >= 1.82 @@ -1063,10 +1120,10 @@ impl BorshDeserialize for std::net::SocketAddr { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let kind = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; match kind { 0 => if _sync { ::deserialize_reader(reader) @@ -1133,15 +1190,15 @@ impl BorshDeserialize for std::net::SocketAddrV4 { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; let port = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; Ok(std::net::SocketAddrV4::new(ip, port)) } } @@ -1156,15 +1213,15 @@ impl BorshDeserialize for std::net::SocketAddrV6 { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let ip = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; let port = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; Ok(std::net::SocketAddrV6::new(ip, port, 0, 0)) } } @@ -1355,72 +1412,10 @@ where } } -#[test] -fn array_deserialization_doesnt_leak() { - use core::sync::atomic::{AtomicUsize, Ordering}; - - static DESERIALIZE_COUNT: AtomicUsize = AtomicUsize::new(0); - static DROP_COUNT: AtomicUsize = AtomicUsize::new(0); - - #[allow(unused)] - struct MyType(u8); - - #[async_generic( - #[cfg(feature = "unstable__async")] - async_variant - )] - impl BorshDeserialize for MyType { - #[async_generic(async_signature(reader: &mut R) -> Result)] - fn deserialize_reader(reader: &mut R) -> Result { - let val = if _sync { - ::deserialize_reader(reader) - } else { - ::deserialize_reader(reader).await - }?; - let v = DESERIALIZE_COUNT.fetch_add(1, Ordering::SeqCst); - if v >= 7 { - panic!("panic in deserialize"); - } - Ok(MyType(val)) - } - } - impl Drop for MyType { - fn drop(&mut self) { - DROP_COUNT.fetch_add(1, Ordering::SeqCst); - } - } - - assert!(<[MyType; 5] as BorshDeserialize>::deserialize(&mut &[0u8; 3][..]).is_err()); - assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 3); - assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 3); - - assert!(<[MyType; 2] as BorshDeserialize>::deserialize(&mut &[0u8; 2][..]).is_ok()); - assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 5); - assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 5); - - #[cfg(feature = "std")] - { - // Test that during a panic in deserialize, the values are still dropped. - let result = std::panic::catch_unwind(|| { - <[MyType; 3] as BorshDeserialize>::deserialize(&mut &[0u8; 3][..]).unwrap(); - }); - assert!(result.is_err()); - assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 8); - assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 7); // 5 because 6 panicked and was not init - } -} - macro_rules! impl_tuple { (@unit $name:ty) => { - #[async_generic( - #[cfg(feature = "unstable__async")] - async_variant - )] impl BorshDeserialize for $name { #[inline] - #[async_generic( - async_signature[ready](_: &mut R) -> impl Future> + Send - )] fn deserialize_reader(_: &mut R) -> Result { Ok(<$name>::default()) } @@ -1428,24 +1423,13 @@ macro_rules! impl_tuple { }; ($($name:ident)+) => { - #[async_generic( - #[cfg(feature = "unstable__async")] - async_variant<$($name),+> - where - $($name: BorshDeserializeAsync,)+ - )] impl<$($name),+> BorshDeserialize for ($($name,)+) where $($name: BorshDeserialize,)+ { #[inline] - #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { - Ok(if _sync { - ($(<$name as BorshDeserialize>::deserialize_reader(reader)?,)+) - } else { - ($(<$name as BorshDeserializeAsync>::deserialize_reader(reader).await?,)+) - }) + Ok(($(<$name as BorshDeserialize>::deserialize_reader(reader)?,)+)) } } }; @@ -1475,6 +1459,55 @@ impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17); impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18); impl_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19); +macro_rules! impl_async_tuple { + (@unit $name:ty) => { + #[cfg(feature = "unstable__async")] + impl BorshDeserializeAsync for $name { + #[inline] + fn deserialize_reader(_: &mut R) -> impl Future> + Send { + core::future::ready(Ok(<$name>::default())) + } + } + }; + + ($($name:ident)+) => { + #[cfg(feature = "unstable__async")] + impl<$($name),+> BorshDeserializeAsync for ($($name,)+) + where + $($name: BorshDeserializeAsync,)+ + { + #[inline] + async fn deserialize_reader(reader: &mut R) -> Result { + Ok(($(<$name as BorshDeserializeAsync>::deserialize_reader(reader).await?,)+)) + } + } + }; +} + +impl_async_tuple!(@unit ()); +impl_async_tuple!(@unit core::ops::RangeFull); + +impl_async_tuple!(T0); +impl_async_tuple!(T0 T1); +impl_async_tuple!(T0 T1 T2); +impl_async_tuple!(T0 T1 T2 T3); +impl_async_tuple!(T0 T1 T2 T3 T4); +impl_async_tuple!(T0 T1 T2 T3 T4 T5); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18); +impl_async_tuple!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16 T17 T18 T19); + macro_rules! impl_range { ($type:ident, $make:expr, $n: literal, $($side:ident),*) => { #[async_generic( @@ -1488,10 +1521,10 @@ macro_rules! impl_range { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let [$($side,)*] = if _sync { - <[T; $n]>::deserialize_reader(reader) + <[T; $n]>::deserialize_reader(reader)? } else { - <[T; $n]>::deserialize_reader(reader).await - }?; + <[T; $n]>::deserialize_reader(reader).await? + }; Ok($make) } } @@ -1532,7 +1565,7 @@ pub mod rc { { #[inline] fn deserialize_reader(reader: &mut R) -> Result { - Ok(>::deserialize_reader(reader)?.into()) + >::deserialize_reader(reader).map(Into::into) } } @@ -1543,10 +1576,10 @@ pub mod rc { /// will end up with a strong count of 1. #[async_generic( #[cfg(feature = "unstable__async")] - async_variant + async_variant where Box: BorshDeserializeAsync, - Self: Send, + T: ?Sized + Sync + Send, )] impl BorshDeserialize for Arc where @@ -1727,3 +1760,109 @@ mod captures { impl Captures for U {} } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn array_deserialization_doesnt_leak() { + use core::sync::atomic::{AtomicUsize, Ordering}; + + static DESERIALIZE_COUNT: AtomicUsize = AtomicUsize::new(0); + static DROP_COUNT: AtomicUsize = AtomicUsize::new(0); + + #[allow(unused)] + struct MyType(u8); + + impl BorshDeserialize for MyType { + fn deserialize_reader(reader: &mut R) -> Result { + let val = ::deserialize_reader(reader)?; + let v = DESERIALIZE_COUNT.fetch_add(1, Ordering::SeqCst); + if v >= 7 { + panic!("panic in deserialize"); + } + Ok(MyType(val)) + } + } + impl Drop for MyType { + fn drop(&mut self) { + DROP_COUNT.fetch_add(1, Ordering::SeqCst); + } + } + + assert!(<[MyType; 5] as BorshDeserialize>::deserialize(&mut &[0u8; 3][..]).is_err()); + assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 3); + assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 3); + + assert!(<[MyType; 2] as BorshDeserialize>::deserialize(&mut &[0u8; 2][..]).is_ok()); + assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 5); + assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 5); + + #[cfg(feature = "std")] + { + // Test that during a panic in deserialize, the values are still dropped. + let result = std::panic::catch_unwind(|| { + <[MyType; 3] as BorshDeserialize>::deserialize(&mut &[0u8; 3][..]).unwrap(); + }); + assert!(result.is_err()); + assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 8); + assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 7); // 5 because 6 panicked and was not init + } + } + + #[cfg(feature = "unstable__tokio")] + #[tokio::test] + async fn async_array_deserialization_doesnt_leak() { + use core::sync::atomic::{AtomicUsize, Ordering}; + + static DESERIALIZE_COUNT: AtomicUsize = AtomicUsize::new(0); + static DROP_COUNT: AtomicUsize = AtomicUsize::new(0); + + #[allow(unused)] + struct MyType(u8); + + impl BorshDeserializeAsync for MyType { + async fn deserialize_reader(reader: &mut R) -> Result { + let val = ::deserialize_reader(reader).await?; + let v = DESERIALIZE_COUNT.fetch_add(1, Ordering::SeqCst); + if v >= 7 { + panic!("panic in deserialize"); + } + Ok(MyType(val)) + } + } + impl Drop for MyType { + fn drop(&mut self) { + DROP_COUNT.fetch_add(1, Ordering::SeqCst); + } + } + + assert!( + <[MyType; 5] as BorshDeserializeAsync>::deserialize_reader(&mut &[0u8; 3][..]) + .await + .is_err() + ); + assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 3); + assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 3); + + assert!( + <[MyType; 2] as BorshDeserializeAsync>::deserialize_reader(&mut &[0u8; 2][..]) + .await + .is_ok() + ); + assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 5); + assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 5); + + // Test that during a panic in deserialize, the values are still dropped. + let result = tokio::spawn(async { + <[MyType; 3] as BorshDeserializeAsync>::deserialize_reader(&mut &[0u8; 3][..]) + .await + .unwrap(); + }) + .await; + assert!(result.is_err_and(|err| err.is_panic())); + assert_eq!(DESERIALIZE_COUNT.load(Ordering::SeqCst), 8); + assert_eq!(DROP_COUNT.load(Ordering::SeqCst), 7); // 5 because 6 panicked and was not init + } +} From d624435581715d4a3b2296cfd2ea71d395d6bc90 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Sun, 23 Feb 2025 01:10:59 +0200 Subject: [PATCH 64/69] Readability fix --- borsh/src/de/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index cc1f1255f..0dcca98ae 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1155,10 +1155,10 @@ impl BorshDeserialize for std::net::IpAddr { #[async_generic(async_signature(reader: &mut R) -> Result)] fn deserialize_reader(reader: &mut R) -> Result { let kind = if _sync { - ::deserialize_reader(reader) + ::deserialize_reader(reader)? } else { - ::deserialize_reader(reader).await - }?; + ::deserialize_reader(reader).await? + }; match kind { 0 => if _sync { ::deserialize_reader(reader) From 6c52ef92de2a7df593886a717ec4934383f319ce Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Fri, 28 Feb 2025 19:41:46 +0200 Subject: [PATCH 65/69] Fix lifetimes. Add `ascii` feature to docs metadata --- borsh/Cargo.toml | 2 +- borsh/src/ser/mod.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/borsh/Cargo.toml b/borsh/Cargo.toml index cbd964757..c26278716 100644 --- a/borsh/Cargo.toml +++ b/borsh/Cargo.toml @@ -52,7 +52,7 @@ insta = "1.29.0" serde_json = { version = "1" } [package.metadata.docs.rs] -features = ["derive", "unstable__schema", "rc", "unsteble__async"] +features = ["derive", "rc", "ascii", "unstable__schema", "unstable__async"] targets = ["x86_64-unknown-linux-gnu"] [features] diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 27596dc80..3a3a22158 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -271,7 +271,7 @@ macro_rules! impl_for_float { impl BorshSerialize for $type { #[inline] #[async_generic( - async_signature<'a, 'w, W: AsyncWrite>(&'a self, writer: &'w mut W) -> Result<()> + async_signature<'a, W: AsyncWrite>(&'a self, writer: &'a mut W) -> Result<()> )] fn serialize(&self, writer: &mut W) -> Result<()> { if self.is_nan() { @@ -943,6 +943,7 @@ where } } +// TODO: use `core` once MSRV >= 1.77 #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "unstable__async")] @@ -975,6 +976,7 @@ impl BorshSerialize for std::net::SocketAddr { } } +// TODO: use `core` once MSRV >= 1.77 #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "unstable__async")] @@ -994,6 +996,7 @@ impl BorshSerialize for std::net::SocketAddrV4 { } } +// TODO: use `core` once MSRV >= 1.77 #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "unstable__async")] @@ -1013,6 +1016,7 @@ impl BorshSerialize for std::net::SocketAddrV6 { } } +// TODO: use `core` once MSRV >= 1.77 #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "unstable__async")] @@ -1042,6 +1046,7 @@ impl BorshSerialize for std::net::Ipv4Addr { } } +// TODO: use `core` once MSRV >= 1.77 #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "unstable__async")] @@ -1071,6 +1076,7 @@ impl BorshSerialize for std::net::Ipv6Addr { } } +// TODO: use `core` once MSRV >= 1.77 #[cfg(feature = "std")] #[async_generic( #[cfg(feature = "unstable__async")] From da103d32c4d14dc0d461d06a6c94ee74b59f8b2f Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Fri, 28 Feb 2025 19:48:22 +0200 Subject: [PATCH 66/69] clippy --- borsh/src/de/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index 0dcca98ae..a68d4175e 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1361,9 +1361,7 @@ where init_count: usize, reader: &'r mut R, } - impl<'r, T: BorshDeserializeAsync, const N: usize, R: AsyncRead> Drop - for ArrayDropGuard<'r, T, N, R> - { + impl Drop for ArrayDropGuard<'_, T, N, R> { fn drop(&mut self) { let init_range = &mut self.buffer[..self.init_count]; // SAFETY: Elements up to self.init_count have been initialized. Assumes this value @@ -1375,7 +1373,7 @@ where } } - impl<'r, T: BorshDeserializeAsync, const N: usize, R: AsyncRead> ArrayDropGuard<'r, T, N, R> { + impl ArrayDropGuard<'_, T, N, R> { unsafe fn transmute_to_array(mut self) -> [T; N] { debug_assert_eq!(self.init_count, N); // Set init_count to 0 so that the values do not get dropped twice. From 253b86832b23669b37e64d72ff5661ae6fd54830 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Fri, 28 Feb 2025 19:48:30 +0200 Subject: [PATCH 67/69] fmt --- borsh/src/ser/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs index 3a3a22158..49a05198d 100644 --- a/borsh/src/ser/mod.rs +++ b/borsh/src/ser/mod.rs @@ -4,6 +4,8 @@ use core::{convert::TryFrom, marker::PhantomData}; use async_generic::async_generic; +#[cfg(feature = "unstable__async")] +use crate::async_io::AsyncWrite; use crate::{ __private::maybestd::{ borrow::{Cow, ToOwned}, @@ -15,8 +17,6 @@ use crate::{ error::check_zst, io::{Error, ErrorKind, Result, Write}, }; -#[cfg(feature = "unstable__async")] -use crate::async_io::AsyncWrite; pub(crate) mod helpers; From e58f2b932fd57782be5999ccfad6c950220c21b4 Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Fri, 28 Feb 2025 20:03:20 +0200 Subject: [PATCH 68/69] make `captures` module public --- borsh/src/de/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index a68d4175e..d2a0b0457 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -1750,10 +1750,11 @@ pub fn from_reader(reader: &mut R) -> Result { #[cfg(feature = "unstable__async")] use captures::Captures; #[cfg(feature = "unstable__async")] -mod captures { +pub mod captures { /// This is a [trick](https://github.com/rust-lang/rfcs/blob/master/text/3498-lifetime-capture-rules-2024.md#the-captures-trick), /// used to not over-restrict the lifetime and trait bounds of a RPIT. - // TODO: Once the MSRV is >=1.82, this should be removed and replaced with `use<>` notation for precise capturing. + /// + /// TODO: Once the MSRV is >=1.82, this should be removed and replaced with `use<>` notation for precise capturing. pub trait Captures {} impl Captures for U {} From 611e8b75c43e1cd613fb9a1796e4d1f343f2b74d Mon Sep 17 00:00:00 2001 From: Danik Vitek Date: Tue, 4 Mar 2025 23:26:52 +0200 Subject: [PATCH 69/69] revert remove `inline` --- borsh/src/de/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs index d2a0b0457..3f9a2c6ee 100644 --- a/borsh/src/de/mod.rs +++ b/borsh/src/de/mod.rs @@ -333,6 +333,7 @@ impl BorshDeserialize for u8 { macro_rules! impl_for_integer { ($type: ident) => { impl BorshDeserialize for $type { + #[inline] fn deserialize_reader(reader: &mut R) -> Result { let mut buf = [0u8; size_of::<$type>()]; reader