From 949f0da7134845fd3155a1c70722b8a2c8962865 Mon Sep 17 00:00:00 2001 From: Igor Gulamov Date: Fri, 4 Dec 2020 20:01:55 +0400 Subject: [PATCH] feat: Add no_std support (#108) --- .travis.yml | 3 +- borsh-rs/CHANGELOG.md | 3 + borsh-rs/benchmarks/Cargo.toml | 5 +- borsh-rs/borsh-derive-internal/Cargo.toml | 2 +- borsh-rs/borsh-derive-internal/src/enum_de.rs | 50 +- .../borsh-derive-internal/src/enum_ser.rs | 16 +- .../borsh-derive-internal/src/struct_de.rs | 18 +- .../borsh-derive-internal/src/struct_ser.rs | 28 +- .../borsh-derive-internal/src/union_de.rs | 4 +- .../borsh-derive-internal/src/union_ser.rs | 4 +- borsh-rs/borsh-derive/Cargo.toml | 8 +- borsh-rs/borsh-derive/src/lib.rs | 34 +- .../borsh-schema-derive-internal/Cargo.toml | 2 +- .../src/enum_schema.rs | 56 +- .../src/helpers.rs | 8 +- .../src/struct_schema.rs | 75 +- borsh-rs/borsh/Cargo.toml | 8 +- borsh-rs/borsh/src/de/hint.rs | 4 +- borsh-rs/borsh/src/de/mod.rs | 197 ++--- borsh-rs/borsh/src/lib.rs | 41 ++ borsh-rs/borsh/src/nostd_io.rs | 691 ++++++++++++++++++ borsh-rs/borsh/src/schema.rs | 16 +- borsh-rs/borsh/src/schema_helpers.rs | 13 +- borsh-rs/borsh/src/ser/mod.rs | 127 ++-- borsh-rs/borsh/tests/test_schema_enums.rs | 5 +- borsh-rs/borsh/tests/test_schema_nested.rs | 7 +- borsh-rs/borsh/tests/test_schema_structs.rs | 7 +- borsh-rs/borsh/tests/test_simple_structs.rs | 2 +- 28 files changed, 1109 insertions(+), 325 deletions(-) create mode 100644 borsh-rs/borsh/src/nostd_io.rs diff --git a/.travis.yml b/.travis.yml index c594be907..8428221c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: rust rust: - stable - beta - - nightly-2019-05-22 + - nightly-2020-05-15 - nightly matrix: @@ -20,6 +20,7 @@ install: script: - cargo build --verbose --manifest-path=borsh-rs/Cargo.toml - cargo test --verbose --manifest-path=borsh-rs/Cargo.toml + - cd borsh-rs/borsh && cargo test --verbose --no-default-features addons: apt: diff --git a/borsh-rs/CHANGELOG.md b/borsh-rs/CHANGELOG.md index f6de16375..0707c4f2d 100644 --- a/borsh-rs/CHANGELOG.md +++ b/borsh-rs/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.8.0 +- Add no_std support. + ## 0.7.2 - Implement `BorshSerialize` for reference fields (`&T`) diff --git a/borsh-rs/benchmarks/Cargo.toml b/borsh-rs/benchmarks/Cargo.toml index 07f29a950..98d3bfbdc 100644 --- a/borsh-rs/benchmarks/Cargo.toml +++ b/borsh-rs/benchmarks/Cargo.toml @@ -11,7 +11,7 @@ bench = false [dependencies] rand_xorshift = "0.2.0" rand = "0.7.0" -borsh = { path = "../borsh" } +borsh = { path = "../borsh", default-features = false } serde = { version = "1.0", features = ["derive"] } speedy-derive = "0.5" speedy = "0.5" @@ -25,3 +25,6 @@ serde_cbor = "0.10" [[bench]] name = "bench" harness = false + +[features] +default = ["borsh/std"] \ No newline at end of file diff --git a/borsh-rs/borsh-derive-internal/Cargo.toml b/borsh-rs/borsh-derive-internal/Cargo.toml index 0c21aa3ee..57cee6fb3 100644 --- a/borsh-rs/borsh-derive-internal/Cargo.toml +++ b/borsh-rs/borsh-derive-internal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "borsh-derive-internal" -version = "0.7.2" +version = "0.8.0" authors = ["Near Inc "] edition = "2018" license = "Apache-2.0" diff --git a/borsh-rs/borsh-derive-internal/src/enum_de.rs b/borsh-rs/borsh-derive-internal/src/enum_de.rs index a4cd7ef5d..61e3a0734 100644 --- a/borsh-rs/borsh-derive-internal/src/enum_de.rs +++ b/borsh-rs/borsh-derive-internal/src/enum_de.rs @@ -1,12 +1,12 @@ -use std::convert::TryFrom; +use core::convert::TryFrom; use quote::quote; use syn::export::TokenStream2; -use syn::{Fields, ItemEnum, WhereClause}; +use syn::{Fields, Ident, ItemEnum, WhereClause}; use crate::attribute_helpers::{contains_initialize_with, contains_skip}; -pub fn enum_de(input: &ItemEnum) -> syn::Result { +pub fn enum_de(input: &ItemEnum, cratename: Ident) -> syn::Result { let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut where_clause = where_clause.map_or_else( @@ -33,11 +33,11 @@ pub fn enum_de(input: &ItemEnum) -> syn::Result { } else { let field_type = &field.ty; where_clause.predicates.push(syn::parse2(quote! { - #field_type: borsh::BorshDeserialize + #field_type: #cratename::BorshDeserialize }).unwrap()); variant_header.extend(quote! { - #field_name: borsh::BorshDeserialize::deserialize(buf)?, + #field_name: #cratename::BorshDeserialize::deserialize(buf)?, }); } } @@ -50,11 +50,11 @@ pub fn enum_de(input: &ItemEnum) -> syn::Result { } else { let field_type = &field.ty; where_clause.predicates.push(syn::parse2(quote! { - #field_type: borsh::BorshDeserialize + #field_type: #cratename::BorshDeserialize }).unwrap()); variant_header - .extend(quote! { borsh::BorshDeserialize::deserialize(buf)?, }); + .extend(quote! { #cratename::BorshDeserialize::deserialize(buf)?, }); } } variant_header = quote! { ( #variant_header )}; @@ -66,20 +66,23 @@ pub fn enum_de(input: &ItemEnum) -> syn::Result { }); } let variant_idx = quote! { - let variant_idx: u8 = borsh::BorshDeserialize::deserialize(buf)?; + let variant_idx: u8 = #cratename::BorshDeserialize::deserialize(buf)?; }; if let Some(method_ident) = init_method { Ok(quote! { - impl #impl_generics borsh::de::BorshDeserialize for #name #ty_generics #where_clause { - fn deserialize(buf: &mut &[u8]) -> std::result::Result { + impl #impl_generics #cratename::de::BorshDeserialize for #name #ty_generics #where_clause { + fn deserialize(buf: &mut &[u8]) -> core::result::Result { #variant_idx let mut return_value = match variant_idx { #variant_arms - _ => - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - format!("Unexpected variant index: {:?}", variant_idx), - )), + _ => { + let msg = #cratename::maybestd::format!("Unexpected variant index: {:?}", variant_idx); + + return Err(#cratename::maybestd::io::Error::new( + #cratename::maybestd::io::ErrorKind::InvalidInput, + msg, + )); + } }; return_value.#method_ident(); Ok(return_value) @@ -88,16 +91,19 @@ pub fn enum_de(input: &ItemEnum) -> syn::Result { }) } else { Ok(quote! { - impl #impl_generics borsh::de::BorshDeserialize for #name #ty_generics #where_clause { - fn deserialize(buf: &mut &[u8]) -> std::result::Result { + impl #impl_generics #cratename::de::BorshDeserialize for #name #ty_generics #where_clause { + fn deserialize(buf: &mut &[u8]) -> core::result::Result { #variant_idx let return_value = match variant_idx { #variant_arms - _ => - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - format!("Unexpected variant index: {:?}", variant_idx), - )), + _ => { + let msg = #cratename::maybestd::format!("Unexpected variant index: {:?}", variant_idx); + + return Err(#cratename::maybestd::io::Error::new( + #cratename::maybestd::io::ErrorKind::InvalidInput, + msg, + )); + } }; Ok(return_value) } diff --git a/borsh-rs/borsh-derive-internal/src/enum_ser.rs b/borsh-rs/borsh-derive-internal/src/enum_ser.rs index 51d98d3cc..e81ebe159 100644 --- a/borsh-rs/borsh-derive-internal/src/enum_ser.rs +++ b/borsh-rs/borsh-derive-internal/src/enum_ser.rs @@ -1,4 +1,4 @@ -use std::convert::TryFrom; +use core::convert::TryFrom; use quote::quote; use syn::export::{Span, TokenStream2}; @@ -6,7 +6,7 @@ use syn::{Fields, Ident, ItemEnum, WhereClause}; use crate::attribute_helpers::contains_skip; -pub fn enum_ser(input: &ItemEnum) -> syn::Result { +pub fn enum_ser(input: &ItemEnum, cratename: Ident) -> syn::Result { let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut where_clause = where_clause.map_or_else( @@ -32,12 +32,12 @@ pub fn enum_ser(input: &ItemEnum) -> syn::Result { } else { let field_type = &field.ty; where_clause.predicates.push(syn::parse2(quote! { - #field_type: borsh::ser::BorshSerialize + #field_type: #cratename::ser::BorshSerialize }).unwrap()); variant_header.extend(quote! { #field_name, }); } variant_body.extend(quote! { - borsh::BorshSerialize::serialize(#field_name, writer)?; + #cratename::BorshSerialize::serialize(#field_name, writer)?; }) } variant_header = quote! { { #variant_header }}; @@ -54,14 +54,14 @@ pub fn enum_ser(input: &ItemEnum) -> syn::Result { } else { let field_type = &field.ty; where_clause.predicates.push(syn::parse2(quote! { - #field_type: borsh::ser::BorshSerialize + #field_type: #cratename::ser::BorshSerialize }).unwrap()); let field_ident = Ident::new(format!("id{}", field_idx).as_str(), Span::call_site()); variant_header.extend(quote! { #field_ident, }); variant_body.extend(quote! { - borsh::BorshSerialize::serialize(#field_ident, writer)?; + #cratename::BorshSerialize::serialize(#field_ident, writer)?; }) } } @@ -78,8 +78,8 @@ pub fn enum_ser(input: &ItemEnum) -> syn::Result { )) } Ok(quote! { - impl #impl_generics borsh::ser::BorshSerialize for #name #ty_generics #where_clause { - fn serialize(&self, writer: &mut W) -> std::result::Result<(), std::io::Error> { + impl #impl_generics #cratename::ser::BorshSerialize for #name #ty_generics #where_clause { + fn serialize(&self, writer: &mut W) -> core::result::Result<(), #cratename::maybestd::io::Error> { match self { #body } diff --git a/borsh-rs/borsh-derive-internal/src/struct_de.rs b/borsh-rs/borsh-derive-internal/src/struct_de.rs index aeca309e6..71a53b077 100644 --- a/borsh-rs/borsh-derive-internal/src/struct_de.rs +++ b/borsh-rs/borsh-derive-internal/src/struct_de.rs @@ -1,9 +1,9 @@ use crate::attribute_helpers::{contains_initialize_with, contains_skip}; use quote::quote; use syn::export::TokenStream2; -use syn::{Fields, ItemStruct, WhereClause}; +use syn::{Fields, Ident, ItemStruct, WhereClause}; -pub fn struct_de(input: &ItemStruct) -> syn::Result { +pub fn struct_de(input: &ItemStruct, cratename: Ident) -> syn::Result { let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut where_clause = where_clause.map_or_else( @@ -26,11 +26,11 @@ pub fn struct_de(input: &ItemStruct) -> syn::Result { } else { let field_type = &field.ty; where_clause.predicates.push(syn::parse2(quote! { - #field_type: borsh::BorshDeserialize + #field_type: #cratename::BorshDeserialize }).unwrap()); quote! { - #field_name: borsh::BorshDeserialize::deserialize(buf)?, + #field_name: #cratename::BorshDeserialize::deserialize(buf)?, } }; body.extend(delta); @@ -43,7 +43,7 @@ pub fn struct_de(input: &ItemStruct) -> syn::Result { let mut body = TokenStream2::new(); for _ in 0..fields.unnamed.len() { let delta = quote! { - borsh::BorshDeserialize::deserialize(buf)?, + #cratename::BorshDeserialize::deserialize(buf)?, }; body.extend(delta); } @@ -59,8 +59,8 @@ pub fn struct_de(input: &ItemStruct) -> syn::Result { }; if let Some(method_ident) = init_method { Ok(quote! { - impl #impl_generics borsh::de::BorshDeserialize for #name #ty_generics #where_clause { - fn deserialize(buf: &mut &[u8]) -> std::result::Result { + impl #impl_generics #cratename::de::BorshDeserialize for #name #ty_generics #where_clause { + fn deserialize(buf: &mut &[u8]) -> core::result::Result { let mut return_value = #return_value; return_value.#method_ident(); Ok(return_value) @@ -69,8 +69,8 @@ pub fn struct_de(input: &ItemStruct) -> syn::Result { }) } else { Ok(quote! { - impl #impl_generics borsh::de::BorshDeserialize for #name #ty_generics #where_clause { - fn deserialize(buf: &mut &[u8]) -> std::result::Result { + impl #impl_generics #cratename::de::BorshDeserialize for #name #ty_generics #where_clause { + fn deserialize(buf: &mut &[u8]) -> core::result::Result { Ok(#return_value) } } diff --git a/borsh-rs/borsh-derive-internal/src/struct_ser.rs b/borsh-rs/borsh-derive-internal/src/struct_ser.rs index 24ba74ab5..1048c2f94 100644 --- a/borsh-rs/borsh-derive-internal/src/struct_ser.rs +++ b/borsh-rs/borsh-derive-internal/src/struct_ser.rs @@ -1,12 +1,12 @@ -use std::convert::TryFrom; +use core::convert::TryFrom; use quote::quote; use syn::export::{Span, TokenStream2}; -use syn::{Fields, Index, ItemStruct, WhereClause}; +use syn::{Fields, Ident, Index, ItemStruct, WhereClause}; use crate::attribute_helpers::contains_skip; -pub fn struct_ser(input: &ItemStruct) -> syn::Result { +pub fn struct_ser(input: &ItemStruct, cratename: Ident) -> syn::Result { let name = &input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); let mut where_clause = where_clause.map_or_else( @@ -25,13 +25,13 @@ pub fn struct_ser(input: &ItemStruct) -> syn::Result { } let field_name = field.ident.as_ref().unwrap(); let delta = quote! { - borsh::BorshSerialize::serialize(&self.#field_name, writer)?; + #cratename::BorshSerialize::serialize(&self.#field_name, writer)?; }; body.extend(delta); let field_type = &field.ty; where_clause.predicates.push(syn::parse2(quote! { - #field_type: borsh::ser::BorshSerialize + #field_type: #cratename::ser::BorshSerialize }).unwrap()); } } @@ -42,7 +42,7 @@ pub fn struct_ser(input: &ItemStruct) -> syn::Result { span: Span::call_site(), }; let delta = quote! { - borsh::BorshSerialize::serialize(&self.#field_idx, writer)?; + #cratename::BorshSerialize::serialize(&self.#field_idx, writer)?; }; body.extend(delta); } @@ -50,8 +50,8 @@ pub fn struct_ser(input: &ItemStruct) -> syn::Result { Fields::Unit => {} } Ok(quote! { - impl #impl_generics borsh::ser::BorshSerialize for #name #ty_generics #where_clause { - fn serialize(&self, writer: &mut W) -> std::result::Result<(), std::io::Error> { + impl #impl_generics #cratename::ser::BorshSerialize for #name #ty_generics #where_clause { + fn serialize(&self, writer: &mut W) -> core::result::Result<(), #cratename::maybestd::io::Error> { #body Ok(()) } @@ -78,14 +78,14 @@ mod tests { } }).unwrap(); - let actual = struct_ser(&item_struct).unwrap(); + let actual = struct_ser(&item_struct, Ident::new("borsh", Span::call_site())).unwrap(); let expected = quote!{ impl borsh::ser::BorshSerialize for A where u64: borsh::ser::BorshSerialize, String: borsh::ser::BorshSerialize { - fn serialize(&self, writer: &mut W) -> std::result::Result<(), std::io::Error> { + fn serialize(&self, writer: &mut W) -> core::result::Result<(), borsh::maybestd::io::Error> { borsh::BorshSerialize::serialize(&self.x, writer)?; borsh::BorshSerialize::serialize(&self.y, writer)?; Ok(()) @@ -104,14 +104,14 @@ mod tests { } }).unwrap(); - let actual = struct_ser(&item_struct).unwrap(); + let actual = struct_ser(&item_struct, Ident::new("borsh", Span::call_site())).unwrap(); let expected = quote!{ impl borsh::ser::BorshSerialize for A where HashMap: borsh::ser::BorshSerialize, String: borsh::ser::BorshSerialize { - fn serialize(&self, writer: &mut W) -> std::result::Result<(), std::io::Error> { + fn serialize(&self, writer: &mut W) -> core::result::Result<(), borsh::maybestd::io::Error> { borsh::BorshSerialize::serialize(&self.x, writer)?; borsh::BorshSerialize::serialize(&self.y, writer)?; Ok(()) @@ -130,7 +130,7 @@ mod tests { } }).unwrap(); - let actual = struct_ser(&item_struct).unwrap(); + let actual = struct_ser(&item_struct, Ident::new("borsh", Span::call_site())).unwrap(); let expected = quote!{ impl borsh::ser::BorshSerialize for A where @@ -138,7 +138,7 @@ mod tests { HashMap: borsh::ser::BorshSerialize, String: borsh::ser::BorshSerialize { - fn serialize(&self, writer: &mut W) -> std::result::Result<(), std::io::Error> { + fn serialize(&self, writer: &mut W) -> core::result::Result<(), borsh::maybestd::io::Error> { borsh::BorshSerialize::serialize(&self.x, writer)?; borsh::BorshSerialize::serialize(&self.y, writer)?; Ok(()) diff --git a/borsh-rs/borsh-derive-internal/src/union_de.rs b/borsh-rs/borsh-derive-internal/src/union_de.rs index 67ffbd3e0..66248169f 100644 --- a/borsh-rs/borsh-derive-internal/src/union_de.rs +++ b/borsh-rs/borsh-derive-internal/src/union_de.rs @@ -1,6 +1,6 @@ use syn::export::TokenStream2; -use syn::ItemUnion; +use syn::{Ident, ItemUnion}; -pub fn union_de(_input: &ItemUnion) -> syn::Result { +pub fn union_de(_input: &ItemUnion, _cratename: Ident) -> syn::Result { unimplemented!() } diff --git a/borsh-rs/borsh-derive-internal/src/union_ser.rs b/borsh-rs/borsh-derive-internal/src/union_ser.rs index 4898629f8..3109f6dbe 100644 --- a/borsh-rs/borsh-derive-internal/src/union_ser.rs +++ b/borsh-rs/borsh-derive-internal/src/union_ser.rs @@ -1,6 +1,6 @@ use syn::export::TokenStream2; -use syn::ItemUnion; +use syn::{Ident, ItemUnion}; -pub fn union_ser(_input: &ItemUnion) -> syn::Result { +pub fn union_ser(_input: &ItemUnion, _cratename: Ident) -> syn::Result { unimplemented!() } diff --git a/borsh-rs/borsh-derive/Cargo.toml b/borsh-rs/borsh-derive/Cargo.toml index c2735a619..f5faa2f58 100644 --- a/borsh-rs/borsh-derive/Cargo.toml +++ b/borsh-rs/borsh-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "borsh-derive" -version = "0.7.2" +version = "0.8.0" authors = ["Near Inc "] edition = "2018" license = "Apache-2.0" @@ -16,7 +16,7 @@ Binary Object Representation Serializer for Hashing proc-macro = true [dependencies] -borsh-derive-internal = { path = "../borsh-derive-internal" , version="0.7.2"} -borsh-schema-derive-internal = { path = "../borsh-schema-derive-internal" , version="0.7.2"} +borsh-derive-internal = { path = "../borsh-derive-internal", version="0.8.0"} +borsh-schema-derive-internal = { path = "../borsh-schema-derive-internal", version="0.8.0"} syn = {version = "1", features = ["full", "fold"] } - +proc-macro-crate = "0.1.5" diff --git a/borsh-rs/borsh-derive/src/lib.rs b/borsh-rs/borsh-derive/src/lib.rs index 97d7d83d8..459b975d1 100644 --- a/borsh-rs/borsh-derive/src/lib.rs +++ b/borsh-rs/borsh-derive/src/lib.rs @@ -2,17 +2,23 @@ extern crate proc_macro; use borsh_derive_internal::*; use borsh_schema_derive_internal::*; use proc_macro::TokenStream; +use proc_macro_crate::crate_name; use syn::export::Span; -use syn::{ItemEnum, ItemStruct, ItemUnion}; +use syn::{Ident, ItemEnum, ItemStruct, ItemUnion}; #[proc_macro_derive(BorshSerialize, attributes(borsh_skip))] pub fn borsh_serialize(input: TokenStream) -> TokenStream { + let cratename = Ident::new( + &crate_name("borsh").unwrap_or("borsh".to_string()), + Span::call_site(), + ); + let res = if let Ok(input) = syn::parse::(input.clone()) { - struct_ser(&input) + struct_ser(&input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - enum_ser(&input) + enum_ser(&input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - union_ser(&input) + union_ser(&input, cratename) } else { // Derive macros can only be defined on structs, enums, and unions. unreachable!() @@ -25,12 +31,17 @@ pub fn borsh_serialize(input: TokenStream) -> TokenStream { #[proc_macro_derive(BorshDeserialize, attributes(borsh_skip, borsh_init))] pub fn borsh_deserialize(input: TokenStream) -> TokenStream { + let cratename = Ident::new( + &crate_name("borsh").unwrap_or("borsh".to_string()), + Span::call_site(), + ); + let res = if let Ok(input) = syn::parse::(input.clone()) { - struct_de(&input) + struct_de(&input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - enum_de(&input) + enum_de(&input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - union_de(&input) + union_de(&input, cratename) } else { // Derive macros can only be defined on structs, enums, and unions. unreachable!() @@ -43,10 +54,15 @@ pub fn borsh_deserialize(input: TokenStream) -> TokenStream { #[proc_macro_derive(BorshSchema, attributes(borsh_skip))] pub fn borsh_schema(input: TokenStream) -> TokenStream { + let cratename = Ident::new( + &crate_name("borsh").unwrap_or("borsh".to_string()), + Span::call_site(), + ); + let res = if let Ok(input) = syn::parse::(input.clone()) { - process_struct(&input) + process_struct(&input, cratename) } else if let Ok(input) = syn::parse::(input.clone()) { - process_enum(&input) + process_enum(&input, cratename) } else if let Ok(_) = syn::parse::(input.clone()) { Err(syn::Error::new( Span::call_site(), diff --git a/borsh-rs/borsh-schema-derive-internal/Cargo.toml b/borsh-rs/borsh-schema-derive-internal/Cargo.toml index f7c73aa9b..9134140ae 100644 --- a/borsh-rs/borsh-schema-derive-internal/Cargo.toml +++ b/borsh-rs/borsh-schema-derive-internal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "borsh-schema-derive-internal" -version = "0.7.2" +version = "0.8.0" authors = ["Near Inc "] edition = "2018" license = "Apache-2.0" diff --git a/borsh-rs/borsh-schema-derive-internal/src/enum_schema.rs b/borsh-rs/borsh-schema-derive-internal/src/enum_schema.rs index 38fb1a6e5..bdea772c7 100644 --- a/borsh-rs/borsh-schema-derive-internal/src/enum_schema.rs +++ b/borsh-rs/borsh-schema-derive-internal/src/enum_schema.rs @@ -6,13 +6,13 @@ use syn::{ Visibility, }; -pub fn process_enum(input: &ItemEnum) -> syn::Result { +pub fn process_enum(input: &ItemEnum, cratename: Ident) -> syn::Result { let name = &input.ident; let name_str = name.to_token_stream().to_string(); let generics = &input.generics; let (impl_generics, ty_generics, _) = generics.split_for_impl(); // Generate function that returns the name of the type. - let (declaration, where_clause) = declaration(&name_str, &input.generics); + let (declaration, where_clause) = declaration(&name_str, &input.generics, cratename.clone()); // Generate function that returns the schema for variants. // Definitions of the variants. @@ -60,7 +60,7 @@ pub fn process_enum(input: &ItemEnum) -> syn::Result { vis: Visibility::Inherited, ident: Some(Ident::new("borsh_schema_phantom_data", Span::call_site())), colon_token: None, - ty: parse_quote! {::std::marker::PhantomData<(#generic_params)>}, + ty: parse_quote! {::core::marker::PhantomData<(#generic_params)>}, }); } Fields::Unnamed(unnamed) => { @@ -69,7 +69,7 @@ pub fn process_enum(input: &ItemEnum) -> syn::Result { vis: Visibility::Inherited, ident: None, colon_token: None, - ty: parse_quote! {::std::marker::PhantomData<(#generic_params)>}, + ty: parse_quote! {::core::marker::PhantomData<(#generic_params)>}, }); } Fields::Unit => { @@ -86,13 +86,13 @@ pub fn process_enum(input: &ItemEnum) -> syn::Result { vis: Visibility::Inherited, ident: None, colon_token: None, - ty: parse_quote! {::std::marker::PhantomData<(#generic_params)>}, + ty: parse_quote! {::core::marker::PhantomData<(#generic_params)>}, }); anonymous_struct.fields = Fields::Unnamed(fields); } } anonymous_defs.extend(quote! { - #[derive(borsh::BorshSchema)] + #[derive(#cratename::BorshSchema)] #anonymous_struct }); add_recursive_defs.extend(quote! { @@ -104,11 +104,11 @@ pub fn process_enum(input: &ItemEnum) -> syn::Result { } let type_definitions = quote! { - fn add_definitions_recursively(definitions: &mut ::std::collections::HashMap) { + fn add_definitions_recursively(definitions: &mut #cratename::maybestd::collections::HashMap<#cratename::schema::Declaration, #cratename::schema::Definition>) { #anonymous_defs #add_recursive_defs - let variants = vec![#(#variants_defs),*]; - let definition = borsh::schema::Definition::Enum{variants}; + let variants = #cratename::maybestd::vec![#(#variants_defs),*]; + let definition = #cratename::schema::Definition::Enum{variants}; Self::add_definition(Self::declaration(), definition, definitions); } }; @@ -118,8 +118,8 @@ pub fn process_enum(input: &ItemEnum) -> syn::Result { TokenStream2::new() }; Ok(quote! { - impl #impl_generics borsh::BorshSchema for #name #ty_generics #where_clause { - fn declaration() -> borsh::schema::Declaration { + impl #impl_generics #cratename::BorshSchema for #name #ty_generics #where_clause { + fn declaration() -> #cratename::schema::Declaration { #declaration } #type_definitions @@ -146,14 +146,14 @@ mod tests { } }).unwrap(); - let actual = process_enum(&item_enum).unwrap(); + let actual = process_enum(&item_enum, Ident::new("borsh", Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A { fn declaration() -> borsh::schema::Declaration { "A".to_string() } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > @@ -164,7 +164,7 @@ mod tests { struct AEggs; ::add_definitions_recursively(definitions); ::add_definitions_recursively(definitions); - let variants = vec![ + let variants = borsh::maybestd::vec![ ("Bacon".to_string(), ::declaration()), ("Eggs".to_string(), ::declaration()) ]; @@ -184,14 +184,14 @@ mod tests { } }).unwrap(); - let actual = process_enum(&item_enum).unwrap(); + let actual = process_enum(&item_enum, Ident::new("borsh", Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A { fn declaration() -> borsh::schema::Declaration { "A".to_string() } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > @@ -199,7 +199,7 @@ mod tests { #[derive(borsh :: BorshSchema)] struct ABacon; ::add_definitions_recursively(definitions); - let variants = vec![("Bacon".to_string(), ::declaration())]; + let variants = borsh::maybestd::vec![("Bacon".to_string(), ::declaration())]; let definition = borsh::schema::Definition::Enum { variants }; Self::add_definition(Self::declaration(), definition, definitions); } @@ -219,14 +219,14 @@ mod tests { } }).unwrap(); - let actual = process_enum(&item_enum).unwrap(); + let actual = process_enum(&item_enum, Ident::new("borsh", Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A { fn declaration() -> borsh::schema::Declaration { "A".to_string() } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > @@ -246,7 +246,7 @@ mod tests { ::add_definitions_recursively(definitions); ::add_definitions_recursively(definitions); ::add_definitions_recursively(definitions); - let variants = vec![ + let variants = borsh::maybestd::vec![ ("Bacon".to_string(), ::declaration()), ("Eggs".to_string(), ::declaration()), ("Salad".to_string(), ::declaration()), @@ -271,7 +271,7 @@ mod tests { } }).unwrap(); - let actual = process_enum(&item_enum).unwrap(); + let actual = process_enum(&item_enum, Ident::new("borsh", Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A where @@ -279,38 +279,38 @@ mod tests { W: borsh::BorshSchema { fn declaration() -> borsh::schema::Declaration { - let params = vec![::declaration(), ::declaration()]; + let params = borsh::maybestd::vec![::declaration(), ::declaration()]; format!(r#"{}<{}>"#, "A", params.join(", ")) } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > ) { #[derive(borsh :: BorshSchema)] - struct ABacon(#[borsh_skip] ::std::marker::PhantomData<(C, W)>); + struct ABacon(#[borsh_skip] ::core::marker::PhantomData<(C, W)>); #[derive(borsh :: BorshSchema)] - struct AEggs(#[borsh_skip] ::std::marker::PhantomData<(C, W)>); + struct AEggs(#[borsh_skip] ::core::marker::PhantomData<(C, W)>); #[derive(borsh :: BorshSchema)] struct ASalad( Tomatoes, C, Oil, - #[borsh_skip] ::std::marker::PhantomData<(C, W)> + #[borsh_skip] ::core::marker::PhantomData<(C, W)> ); #[derive(borsh :: BorshSchema)] struct ASausage { wrapper: W, filling: Filling, #[borsh_skip] - borsh_schema_phantom_data: ::std::marker::PhantomData<(C, W)> + borsh_schema_phantom_data: ::core::marker::PhantomData<(C, W)> } >::add_definitions_recursively(definitions); >::add_definitions_recursively(definitions); >::add_definitions_recursively(definitions); >::add_definitions_recursively(definitions); - let variants = vec![ + let variants = borsh::maybestd::vec![ ("Bacon".to_string(), >::declaration()), ("Eggs".to_string(), >::declaration()), ("Salad".to_string(), >::declaration()), diff --git a/borsh-rs/borsh-schema-derive-internal/src/helpers.rs b/borsh-rs/borsh-schema-derive-internal/src/helpers.rs index 4d4a44627..87781ec05 100644 --- a/borsh-rs/borsh-schema-derive-internal/src/helpers.rs +++ b/borsh-rs/borsh-schema-derive-internal/src/helpers.rs @@ -1,6 +1,6 @@ use quote::{quote, ToTokens}; use syn::export::TokenStream2; -use syn::{Attribute, Generics, Meta}; +use syn::{Attribute, Generics, Meta, Ident}; pub fn contains_skip(attrs: &[Attribute]) -> bool { for attr in attrs.iter() { @@ -13,7 +13,7 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { false } -pub fn declaration(ident_str: &String, generics: &Generics) -> (TokenStream2, Vec) { +pub fn declaration(ident_str: &String, generics: &Generics, cratename: Ident) -> (TokenStream2, Vec) { let (_, _, where_clause_generics) = generics.split_for_impl(); // Generate function that returns the name of the type. let mut declaration_params = vec![]; @@ -28,7 +28,7 @@ pub fn declaration(ident_str: &String, generics: &Generics) -> (TokenStream2, Ve <#type_param_name>::declaration() }); where_clause.push(quote! { - #type_param_name: borsh::BorshSchema + #type_param_name: #cratename::BorshSchema }); } let result = if declaration_params.is_empty() { @@ -37,7 +37,7 @@ pub fn declaration(ident_str: &String, generics: &Generics) -> (TokenStream2, Ve } } else { quote! { - let params = vec![#(#declaration_params),*]; + let params = #cratename::maybestd::vec![#(#declaration_params),*]; format!(r#"{}<{}>"#, #ident_str, params.join(", ")) } }; diff --git a/borsh-rs/borsh-schema-derive-internal/src/struct_schema.rs b/borsh-rs/borsh-schema-derive-internal/src/struct_schema.rs index e8cc35454..e624fb489 100644 --- a/borsh-rs/borsh-schema-derive-internal/src/struct_schema.rs +++ b/borsh-rs/borsh-schema-derive-internal/src/struct_schema.rs @@ -1,15 +1,16 @@ use crate::helpers::{contains_skip, declaration}; use quote::quote; use syn::export::{ToTokens, TokenStream2}; -use syn::{Fields, ItemStruct}; +use syn::{Fields, ItemStruct, Ident}; -pub fn process_struct(input: &ItemStruct) -> syn::Result { + +pub fn process_struct(input: &ItemStruct, cratename: Ident) -> syn::Result { let name = &input.ident; let name_str = name.to_token_stream().to_string(); let generics = &input.generics; let (impl_generics, ty_generics, _) = generics.split_for_impl(); // Generate function that returns the name of the type. - let (declaration, mut where_clause) = declaration(&name_str, &input.generics); + let (declaration, mut where_clause) = declaration(&name_str, &input.generics, cratename.clone()); // Generate function that returns the schema of required types. let mut fields_vec = vec![]; @@ -30,12 +31,12 @@ pub fn process_struct(input: &ItemStruct) -> syn::Result { <#field_type>::add_definitions_recursively(definitions); }); where_clause.push(quote! { - #field_type: borsh::BorshSchema + #field_type: #cratename::BorshSchema }); } if !fields_vec.is_empty() { struct_fields = quote! { - let fields = borsh::schema::Fields::NamedFields(vec![#(#fields_vec),*]); + let fields = #cratename::schema::Fields::NamedFields(#cratename::maybestd::vec![#(#fields_vec),*]); }; } } @@ -52,12 +53,12 @@ pub fn process_struct(input: &ItemStruct) -> syn::Result { <#field_type>::add_definitions_recursively(definitions); }); where_clause.push(quote! { - #field_type: borsh::BorshSchema + #field_type: #cratename::BorshSchema }); } if !fields_vec.is_empty() { struct_fields = quote! { - let fields = borsh::schema::Fields::UnnamedFields(vec![#(#fields_vec),*]); + let fields = #cratename::schema::Fields::UnnamedFields(#cratename::maybestd::vec![#(#fields_vec),*]); }; } } @@ -66,14 +67,14 @@ pub fn process_struct(input: &ItemStruct) -> syn::Result { if fields_vec.is_empty() { struct_fields = quote! { - let fields = borsh::schema::Fields::Empty; + let fields = #cratename::schema::Fields::Empty; }; } let add_definitions_recursively = quote! { - fn add_definitions_recursively(definitions: &mut ::std::collections::HashMap) { + fn add_definitions_recursively(definitions: &mut #cratename::maybestd::collections::HashMap<#cratename::schema::Declaration, #cratename::schema::Definition>) { #struct_fields - let definition = borsh::schema::Definition::Struct { fields }; + let definition = #cratename::schema::Definition::Struct { fields }; Self::add_definition(Self::declaration(), definition, definitions); #add_definitions_recursively_rec } @@ -84,8 +85,8 @@ pub fn process_struct(input: &ItemStruct) -> syn::Result { TokenStream2::new() }; Ok(quote! { - impl #impl_generics borsh::BorshSchema for #name #ty_generics #where_clause { - fn declaration() -> borsh::schema::Declaration { + impl #impl_generics #cratename::BorshSchema for #name #ty_generics #where_clause { + fn declaration() -> #cratename::schema::Declaration { #declaration } #add_definitions_recursively @@ -110,14 +111,14 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A { fn declaration() -> borsh::schema::Declaration { "A".to_string() } - fn add_definitions_recursively(definitions: &mut ::std::collections::HashMap) { + fn add_definitions_recursively(definitions: &mut borsh::maybestd::collections::HashMap) { let fields = borsh::schema::Fields::Empty; let definition = borsh::schema::Definition::Struct { fields }; Self::add_definition(Self::declaration(), definition, definitions); @@ -134,7 +135,7 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A where @@ -142,16 +143,16 @@ mod tests { T: borsh::BorshSchema { fn declaration() -> borsh::schema::Declaration { - let params = vec![::declaration()]; + let params = borsh::maybestd::vec![::declaration()]; format!(r#"{}<{}>"#, "A", params.join(", ")) } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > ) { - let fields = borsh::schema::Fields::UnnamedFields(vec![::declaration()]); + let fields = borsh::schema::Fields::UnnamedFields(borsh::maybestd::vec![::declaration()]); let definition = borsh::schema::Definition::Struct { fields }; Self::add_definition(Self::declaration(), definition, definitions); ::add_definitions_recursively(definitions); @@ -168,7 +169,7 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A where @@ -179,12 +180,12 @@ mod tests { "A".to_string() } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > ) { - let fields = borsh::schema::Fields::UnnamedFields(vec![ + let fields = borsh::schema::Fields::UnnamedFields(borsh::maybestd::vec![ ::declaration(), ::declaration() ]); @@ -205,7 +206,7 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A where @@ -215,17 +216,17 @@ mod tests { V: borsh::BorshSchema { fn declaration() -> borsh::schema::Declaration { - let params = vec![::declaration(), ::declaration()]; + let params = borsh::maybestd::vec![::declaration(), ::declaration()]; format!(r#"{}<{}>"#, "A", params.join(", ")) } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > ) { let fields = - borsh::schema::Fields::UnnamedFields(vec![::declaration(), ::declaration()]); + borsh::schema::Fields::UnnamedFields(borsh::maybestd::vec![::declaration(), ::declaration()]); let definition = borsh::schema::Definition::Struct { fields }; Self::add_definition(Self::declaration(), definition, definitions); ::add_definitions_recursively(definitions); @@ -246,7 +247,7 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A where @@ -257,12 +258,12 @@ mod tests { "A".to_string() } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > ) { - let fields = borsh::schema::Fields::NamedFields(vec![ + let fields = borsh::schema::Fields::NamedFields(borsh::maybestd::vec![ ("x".to_string(), ::declaration()), ("y".to_string(), ::declaration()) ]); @@ -286,7 +287,7 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A where @@ -296,16 +297,16 @@ mod tests { String: borsh::BorshSchema { fn declaration() -> borsh::schema::Declaration { - let params = vec![::declaration(), ::declaration()]; + let params = borsh::maybestd::vec![::declaration(), ::declaration()]; format!(r#"{}<{}>"#, "A", params.join(", ")) } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > ) { - let fields = borsh::schema::Fields::NamedFields(vec![ + let fields = borsh::schema::Fields::NamedFields(borsh::maybestd::vec![ ("x".to_string(), >::declaration()), ("y".to_string(), ::declaration()) ]); @@ -326,14 +327,14 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A { fn declaration() -> borsh::schema::Declaration { "A".to_string() } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > @@ -354,7 +355,7 @@ mod tests { }) .unwrap(); - let actual = process_struct(&item_struct).unwrap(); + let actual = process_struct(&item_struct, Ident::new("borsh", proc_macro2::Span::call_site())).unwrap(); let expected = quote!{ impl borsh::BorshSchema for A where @@ -364,12 +365,12 @@ mod tests { "A".to_string() } fn add_definitions_recursively( - definitions: &mut ::std::collections::HashMap< + definitions: &mut borsh::maybestd::collections::HashMap< borsh::schema::Declaration, borsh::schema::Definition > ) { - let fields = borsh::schema::Fields::UnnamedFields(vec![::declaration()]); + let fields = borsh::schema::Fields::UnnamedFields(borsh::maybestd::vec![::declaration()]); let definition = borsh::schema::Definition::Struct { fields }; Self::add_definition(Self::declaration(), definition, definitions); ::add_definitions_recursively(definitions); diff --git a/borsh-rs/borsh/Cargo.toml b/borsh-rs/borsh/Cargo.toml index 1e5973e6c..dde5ee7f7 100644 --- a/borsh-rs/borsh/Cargo.toml +++ b/borsh-rs/borsh/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "borsh" -version = "0.7.2" +version = "0.8.0" authors = ["Near Inc "] edition = "2018" license = "Apache-2.0" @@ -21,11 +21,9 @@ name = "generate_schema_schema" path = "src/generate_schema_schema.rs" [dependencies] -borsh-derive = { path = "../borsh-derive", version = "0.7.2" } +borsh-derive = { path = "../borsh-derive", version = "0.8.0" } +hashbrown = "0.9.1" [features] default = ["std"] - -# Provides impls for common standard library types like Vec. -# Requires a dependency on the Rust standard library. std = [] diff --git a/borsh-rs/borsh/src/de/hint.rs b/borsh-rs/borsh/src/de/hint.rs index 8ef5c06f2..7af550cef 100644 --- a/borsh-rs/borsh/src/de/hint.rs +++ b/borsh-rs/borsh/src/de/hint.rs @@ -1,7 +1,7 @@ #[inline] pub fn cautious(hint: u32) -> usize { - let el_size = std::mem::size_of::() as u32; - std::cmp::max(std::cmp::min(hint, 4096 / el_size), 1) as usize + let el_size = core::mem::size_of::() as u32; + core::cmp::max(core::cmp::min(hint, 4096 / el_size), 1) as usize } #[cfg(test)] diff --git a/borsh-rs/borsh/src/de/mod.rs b/borsh-rs/borsh/src/de/mod.rs index 639eb8564..ec3c75eed 100644 --- a/borsh-rs/borsh/src/de/mod.rs +++ b/borsh-rs/borsh/src/de/mod.rs @@ -1,8 +1,23 @@ -use std::borrow::Cow; -use std::collections::{BTreeMap, HashMap, HashSet}; -use std::convert::TryInto; -use std::io; -use std::mem::{forget, size_of}; +use core::{ + convert::TryInto, + hash::Hash, + mem::{forget, size_of} +}; + +use crate::maybestd::{ + io::{Error, ErrorKind, Result}, + borrow::{ + Cow, + ToOwned, + Borrow + }, + collections::{BTreeMap, HashMap, HashSet}, + format, + string::{String, ToString}, + vec::Vec, + boxed::Box +}; + mod hint; @@ -13,15 +28,15 @@ const ERROR_UNEXPECTED_LENGTH_OF_INPUT: &str = "Unexpected length of input"; pub trait BorshDeserialize: Sized { /// Deserializes this instance from a given slice of bytes. /// Updates the buffer to point at the remaining bytes. - fn deserialize(buf: &mut &[u8]) -> io::Result; + fn deserialize(buf: &mut &[u8]) -> Result; /// Deserialize this instance from a slice of bytes. - fn try_from_slice(v: &[u8]) -> io::Result { + fn try_from_slice(v: &[u8]) -> Result { let mut v_mut = v; let result = Self::deserialize(&mut v_mut)?; if !v_mut.is_empty() { - return Err(io::Error::new( - io::ErrorKind::InvalidData, + return Err(Error::new( + ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ, )); } @@ -41,10 +56,10 @@ pub trait BorshDeserialize: Sized { impl BorshDeserialize for u8 { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.is_empty() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -63,10 +78,10 @@ macro_rules! impl_for_integer { ($type: ident) => { impl BorshDeserialize for $type { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.len() < size_of::<$type>() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -94,10 +109,10 @@ macro_rules! impl_for_float { ($type: ident, $int_type: ident) => { impl BorshDeserialize for $type { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.len() < size_of::<$type>() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -106,8 +121,8 @@ macro_rules! impl_for_float { )); *buf = &buf[size_of::<$int_type>()..]; if res.is_nan() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, "For portability reasons we do not allow to deserialize NaNs.", )); } @@ -122,10 +137,10 @@ impl_for_float!(f64, u64); impl BorshDeserialize for bool { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.is_empty() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -136,23 +151,27 @@ impl BorshDeserialize for bool { } else if b == 1 { Ok(true) } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("Invalid bool representation: {}", b), + let msg = format!("Invalid bool representation: {}", b); + + Err(Error::new( + ErrorKind::InvalidInput, + msg, )) } } } + + impl BorshDeserialize for Option where T: BorshDeserialize, { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.is_empty() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -163,27 +182,29 @@ where } else if flag == 1 { Ok(Some(T::deserialize(buf)?)) } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!( - "Invalid Option representation: {}. The first byte must be 0 or 1", - flag - ), + let msg = format!( + "Invalid Option representation: {}. The first byte must be 0 or 1", + flag + ); + + Err(Error::new( + ErrorKind::InvalidInput, + msg, )) } } } -impl BorshDeserialize for std::result::Result +impl BorshDeserialize for core::result::Result where T: BorshDeserialize, E: BorshDeserialize, { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.is_empty() { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -194,12 +215,14 @@ where } else if flag == 1 { Ok(Ok(T::deserialize(buf)?)) } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!( - "Invalid Result representation: {}. The first byte must be 0 or 1", - flag - ), + let msg = format!( + "Invalid Result representation: {}. The first byte must be 0 or 1", + flag + ); + + Err(Error::new( + ErrorKind::InvalidInput, + msg, )) } } @@ -207,27 +230,29 @@ where impl BorshDeserialize for String { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { String::from_utf8(Vec::::deserialize(buf)?) - .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err.to_string())) + .map_err(|err| { + let msg = err.to_string(); + Error::new(ErrorKind::InvalidData, msg) + }) } } -#[cfg(feature = "std")] impl BorshDeserialize for Vec where T: BorshDeserialize, { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let len = u32::deserialize(buf)?; if len == 0 { Ok(Vec::new()) } else if T::is_u8() && size_of::() == size_of::() { - let len = len.try_into().map_err(|_| io::ErrorKind::InvalidInput)?; + let len = len.try_into().map_err(|_| ErrorKind::InvalidInput)?; if buf.len() < len { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -244,7 +269,7 @@ where // `T::is_u8()` is a workaround for not being able to implement `Vec` separately. let result = unsafe { // Ensure the original vector is not dropped. - let mut v_clone = std::mem::ManuallyDrop::new(result); + let mut v_clone = core::mem::ManuallyDrop::new(result); Vec::from_raw_parts( v_clone.as_mut_ptr() as *mut T, v_clone.len(), @@ -259,7 +284,7 @@ where let p = result.as_mut_ptr(); unsafe { forget(result); - let len = len.try_into().map_err(|_| io::ErrorKind::InvalidInput)?; + let len = len.try_into().map_err(|_| ErrorKind::InvalidInput)?; let result = Vec::from_raw_parts(p, len, len); Ok(result) } @@ -276,35 +301,35 @@ where impl BorshDeserialize for Cow<'_, T> where - T: std::borrow::ToOwned + ?Sized, + T: ToOwned + ?Sized, T::Owned: BorshDeserialize, { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { Ok(Cow::Owned(BorshDeserialize::deserialize(buf)?)) } } -#[cfg(feature = "std")] + impl BorshDeserialize for HashSet where - T: BorshDeserialize + Eq + std::hash::Hash, + T: BorshDeserialize + Eq + Hash, { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let vec = >::deserialize(buf)?; Ok(vec.into_iter().collect::>()) } } -#[cfg(feature = "std")] + impl BorshDeserialize for HashMap where - K: BorshDeserialize + Eq + std::hash::Hash, + K: BorshDeserialize + Eq + Hash, V: BorshDeserialize, { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let len = u32::deserialize(buf)?; // TODO(16): return capacity allocation when we can safely do that. let mut result = HashMap::new(); @@ -317,14 +342,14 @@ where } } -#[cfg(feature = "std")] + impl BorshDeserialize for BTreeMap where - K: BorshDeserialize + Ord + std::hash::Hash, + K: BorshDeserialize + Ord + core::hash::Hash, V: BorshDeserialize, { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let len = u32::deserialize(buf)?; let mut result = BTreeMap::new(); for _ in 0..len { @@ -339,13 +364,13 @@ where #[cfg(feature = "std")] impl BorshDeserialize for std::net::SocketAddr { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let kind = u8::deserialize(buf)?; match kind { 0 => std::net::SocketAddrV4::deserialize(buf).map(std::net::SocketAddr::V4), 1 => std::net::SocketAddrV6::deserialize(buf).map(std::net::SocketAddr::V6), - value => Err(io::Error::new( - io::ErrorKind::InvalidInput, + value => Err(Error::new( + ErrorKind::InvalidInput, format!("Invalid SocketAddr variant: {}", value), )), } @@ -355,7 +380,7 @@ impl BorshDeserialize for std::net::SocketAddr { #[cfg(feature = "std")] impl BorshDeserialize for std::net::SocketAddrV4 { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let ip = std::net::Ipv4Addr::deserialize(buf)?; let port = u16::deserialize(buf)?; Ok(std::net::SocketAddrV4::new(ip, port)) @@ -365,7 +390,7 @@ impl BorshDeserialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] impl BorshDeserialize for std::net::SocketAddrV6 { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let ip = std::net::Ipv6Addr::deserialize(buf)?; let port = u16::deserialize(buf)?; Ok(std::net::SocketAddrV6::new(ip, port, 0, 0)) @@ -375,10 +400,10 @@ impl BorshDeserialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] impl BorshDeserialize for std::net::Ipv4Addr { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.len() < 4 { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -392,10 +417,10 @@ impl BorshDeserialize for std::net::Ipv4Addr { #[cfg(feature = "std")] impl BorshDeserialize for std::net::Ipv6Addr { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { if buf.len() < 16 { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } @@ -408,11 +433,11 @@ impl BorshDeserialize for std::net::Ipv6Addr { impl BorshDeserialize for Box where - U: Into> + std::borrow::Borrow, - T: std::borrow::ToOwned + ?Sized, + U: Into> + Borrow, + T: ToOwned + ?Sized, T::Owned: BorshDeserialize, { - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { Ok(T::Owned::deserialize(buf)?.into()) } } @@ -425,18 +450,18 @@ macro_rules! impl_arrays { T: BorshDeserialize + Default + Copy { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { let mut result = [T::default(); $len]; if T::is_u8() && size_of::() == size_of::() { if buf.len() < $len { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, + return Err(Error::new( + ErrorKind::InvalidInput, ERROR_UNEXPECTED_LENGTH_OF_INPUT, )); } // The size of the memory should match because `size_of::() == size_of::()`. // `T::is_u8()` is a workaround for not being able to implement `[u8; *]` separately. - result.copy_from_slice(unsafe { std::slice::from_raw_parts(buf.as_ptr() as *const T, $len) }); + result.copy_from_slice(unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const T, $len) }); *buf = &buf[$len..]; } else { for i in 0..$len { @@ -457,13 +482,13 @@ where T: BorshDeserialize + Default + Copy, { #[inline] - fn deserialize(_buf: &mut &[u8]) -> io::Result { + fn deserialize(_buf: &mut &[u8]) -> Result { Ok([T::default(); 0]) } } impl BorshDeserialize for () { - fn deserialize(_buf: &mut &[u8]) -> io::Result { + fn deserialize(_buf: &mut &[u8]) -> Result { Ok(()) } } @@ -474,7 +499,7 @@ macro_rules! impl_tuple { where $($name: BorshDeserialize,)+ { #[inline] - fn deserialize(buf: &mut &[u8]) -> io::Result { + fn deserialize(buf: &mut &[u8]) -> Result { Ok(($($name::deserialize(buf)?,)+)) } diff --git a/borsh-rs/borsh/src/lib.rs b/borsh-rs/borsh/src/lib.rs index 6058a5da2..38916f82c 100644 --- a/borsh-rs/borsh/src/lib.rs +++ b/borsh-rs/borsh/src/lib.rs @@ -1,3 +1,8 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate alloc; + pub use borsh_derive::{BorshDeserialize, BorshSchema, BorshSerialize}; pub mod de; @@ -5,7 +10,43 @@ pub mod schema; pub mod schema_helpers; pub mod ser; + pub use de::BorshDeserialize; pub use schema::BorshSchema; pub use schema_helpers::{try_from_slice_with_schema, try_to_vec_with_schema}; pub use ser::BorshSerialize; + +/// A facade around all the types we need from the `std`, `core`, and `alloc` +/// crates. This avoids elaborate import wrangling having to happen in every +/// module. +#[cfg(feature = "std")] +pub mod maybestd { + pub use std::{ + borrow, string, vec, format, boxed, rc, sync, collections, io + }; +} + +#[cfg(not(feature = "std"))] +mod nostd_io; + +#[cfg(not(feature = "std"))] +pub mod maybestd { + pub use alloc::{ + borrow, string, vec, format, boxed, rc, sync, + }; + + pub mod collections { + pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; + pub use hashbrown::*; + } + + pub mod io { + pub use super::super::nostd_io::*; + } + + pub use hashbrown::{HashMap, HashSet}; + + pub mod hash_map { + pub use hashbrown::hash_map::Entry; + } +} diff --git a/borsh-rs/borsh/src/nostd_io.rs b/borsh-rs/borsh/src/nostd_io.rs new file mode 100644 index 000000000..16eb425e8 --- /dev/null +++ b/borsh-rs/borsh/src/nostd_io.rs @@ -0,0 +1,691 @@ +//! Taken from https://github.com/bbqsrc/bare-io (with adjustments) + +use core::{convert::From, fmt, result}; +use crate::maybestd::string::String; + +/// A specialized [`Result`] type for I/O operations. +/// +/// This type is broadly used across [`std::io`] for any operation which may +/// produce an error. +/// +/// This typedef is generally used to avoid writing out [`io::Error`] directly and +/// is otherwise a direct mapping to [`Result`]. +/// +/// While usual Rust style is to import types directly, aliases of [`Result`] +/// often are not, to make it easier to distinguish between them. [`Result`] is +/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias +/// will generally use `io::Result` instead of shadowing the [prelude]'s import +/// of [`std::result::Result`][`Result`]. +/// +/// [`std::io`]: crate::io +/// [`io::Error`]: Error +/// [`Result`]: crate::result::Result +/// [prelude]: crate::prelude +/// +/// # Examples +/// +/// A convenience function that bubbles an `io::Result` to its caller: +/// +/// ``` +/// use std::io; +/// +/// fn get_string() -> io::Result { +/// let mut buffer = String::new(); +/// +/// io::stdin().read_line(&mut buffer)?; +/// +/// Ok(buffer) +/// } +/// ``` +pub type Result = result::Result; + +/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and +/// associated traits. +/// +/// Errors mostly originate from the underlying OS, but custom instances of +/// `Error` can be created with crafted error messages and a particular value of +/// [`ErrorKind`]. +/// +/// [`Read`]: crate::io::Read +/// [`Write`]: crate::io::Write +/// [`Seek`]: crate::io::Seek +pub struct Error { + repr: Repr, +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.repr, f) + } +} + +enum Repr { + Simple(ErrorKind), + Custom(Custom), +} + +#[derive(Debug)] +struct Custom { + kind: ErrorKind, + error: String, +} + +/// A list specifying general categories of I/O error. +/// +/// This list is intended to grow over time and it is not recommended to +/// exhaustively match against it. +/// +/// It is used with the [`io::Error`] type. +/// +/// [`io::Error`]: Error +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +// #[allow(deprecated)] +#[non_exhaustive] +pub enum ErrorKind { + /// An entity was not found, often a file. + NotFound, + /// The operation lacked the necessary privileges to complete. + PermissionDenied, + /// The connection was refused by the remote server. + ConnectionRefused, + /// The connection was reset by the remote server. + ConnectionReset, + /// The connection was aborted (terminated) by the remote server. + ConnectionAborted, + /// The network operation failed because it was not connected yet. + NotConnected, + /// A socket address could not be bound because the address is already in + /// use elsewhere. + AddrInUse, + /// A nonexistent interface was requested or the requested address was not + /// local. + AddrNotAvailable, + /// The operation failed because a pipe was closed. + BrokenPipe, + /// An entity already exists, often a file. + AlreadyExists, + /// The operation needs to block to complete, but the blocking operation was + /// requested to not occur. + WouldBlock, + /// A parameter was incorrect. + InvalidInput, + /// Data not valid for the operation were encountered. + /// + /// Unlike [`InvalidInput`], this typically means that the operation + /// parameters were valid, however the error was caused by malformed + /// input data. + /// + /// For example, a function that reads a file into a string will error with + /// `InvalidData` if the file's contents are not valid UTF-8. + /// + /// [`InvalidInput`]: ErrorKind::InvalidInput + InvalidData, + /// The I/O operation's timeout expired, causing it to be canceled. + TimedOut, + /// An error returned when an operation could not be completed because a + /// call to [`write`] returned [`Ok(0)`]. + /// + /// This typically means that an operation could only succeed if it wrote a + /// particular number of bytes but only a smaller number of bytes could be + /// written. + /// + /// [`write`]: crate::io::Write::write + /// [`Ok(0)`]: Ok + WriteZero, + /// This operation was interrupted. + /// + /// Interrupted operations can typically be retried. + Interrupted, + /// Any I/O error not part of this list. + /// + /// Errors that are `Other` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Other` and to expect any additional characteristics, + /// e.g., a specific [`Error::raw_os_error`] return value. + Other, + + /// An error returned when an operation could not be completed because an + /// "end of file" was reached prematurely. + /// + /// This typically means that an operation could only succeed if it read a + /// particular number of bytes but only a smaller number of bytes could be + /// read. + UnexpectedEof, +} + +impl ErrorKind { + pub(crate) fn as_str(&self) -> &'static str { + match *self { + ErrorKind::NotFound => "entity not found", + ErrorKind::PermissionDenied => "permission denied", + ErrorKind::ConnectionRefused => "connection refused", + ErrorKind::ConnectionReset => "connection reset", + ErrorKind::ConnectionAborted => "connection aborted", + ErrorKind::NotConnected => "not connected", + ErrorKind::AddrInUse => "address in use", + ErrorKind::AddrNotAvailable => "address not available", + ErrorKind::BrokenPipe => "broken pipe", + ErrorKind::AlreadyExists => "entity already exists", + ErrorKind::WouldBlock => "operation would block", + ErrorKind::InvalidInput => "invalid input parameter", + ErrorKind::InvalidData => "invalid data", + ErrorKind::TimedOut => "timed out", + ErrorKind::WriteZero => "write zero", + ErrorKind::Interrupted => "operation interrupted", + ErrorKind::Other => "other os error", + ErrorKind::UnexpectedEof => "unexpected end of file", + } + } +} + +/// Intended for use for errors not exposed to the user, where allocating onto +/// the heap (for normal construction via Error::new) is too costly. +impl From for Error { + /// Converts an [`ErrorKind`] into an [`Error`]. + /// + /// This conversion allocates a new error with a simple representation of error kind. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// let not_found = ErrorKind::NotFound; + /// let error = Error::from(not_found); + /// assert_eq!("entity not found", format!("{}", error)); + /// ``` + #[inline] + fn from(kind: ErrorKind) -> Error { + Error { + repr: Repr::Simple(kind), + } + } +} + +impl Error { + /// Creates a new I/O error from a known kind of error as well as an + /// arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. The `error` argument is an arbitrary + /// payload which will be contained in this [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// // errors can be created from strings + /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// ``` + 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 }), + } + } + + /// Returns a reference to the inner error wrapped by this error (if any). + /// + /// If this [`Error`] was constructed via [`new`] then this function will + /// return [`Some`], otherwise it will return [`None`]. + /// + /// [`new`]: Error::new + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// fn print_error(err: &Error) { + /// if let Some(inner_err) = err.get_ref() { + /// println!("Inner error: {:?}", inner_err); + /// } else { + /// println!("No inner error"); + /// } + /// } + /// + /// fn main() { + /// // Will print "No inner error". + /// print_error(&Error::last_os_error()); + /// // Will print "Inner error: ...". + /// print_error(&Error::new(ErrorKind::Other, "oh no!")); + /// } + /// ``` + pub fn get_ref(&self) -> Option<&str> { + match self.repr { + Repr::Simple(..) => None, + Repr::Custom(ref c) => Some(&c.error), + } + } + + /// Consumes the `Error`, returning its inner error (if any). + /// + /// If this [`Error`] was constructed via [`new`] then this function will + /// return [`Some`], otherwise it will return [`None`]. + /// + /// [`new`]: Error::new + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// fn print_error(err: Error) { + /// if let Some(inner_err) = err.into_inner() { + /// println!("Inner error: {}", inner_err); + /// } else { + /// println!("No inner error"); + /// } + /// } + /// + /// fn main() { + /// // Will print "No inner error". + /// print_error(Error::last_os_error()); + /// // Will print "Inner error: ...". + /// print_error(Error::new(ErrorKind::Other, "oh no!")); + /// } + /// ``` + pub fn into_inner(self) -> Option { + match self.repr { + Repr::Simple(..) => None, + Repr::Custom(c) => Some(c.error), + } + } + + /// Returns the corresponding [`ErrorKind`] for this error. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// fn print_error(err: Error) { + /// println!("{:?}", err.kind()); + /// } + /// + /// fn main() { + /// // Will print "Other". + /// print_error(Error::last_os_error()); + /// // Will print "AddrInUse". + /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); + /// } + /// ``` + pub fn kind(&self) -> ErrorKind { + match self.repr { + Repr::Custom(ref c) => c.kind, + Repr::Simple(kind) => kind, + } + } +} + +impl fmt::Debug for Repr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt), + Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.repr { + Repr::Custom(ref c) => c.error.fmt(fmt), + Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()), + } + } +} + +fn _assert_error_is_sync_send() { + fn _is_sync_send() {} + _is_sync_send::(); +} + + +/// A trait for objects which are byte-oriented sinks. +/// +/// Implementors of the `Write` trait are sometimes called 'writers'. +/// +/// Writers are defined by two required methods, [`write`] and [`flush`]: +/// +/// * The [`write`] method will attempt to write some data into the object, +/// returning how many bytes were successfully written. +/// +/// * The [`flush`] method is useful for adaptors and explicit buffers +/// themselves for ensuring that all buffered data has been pushed out to the +/// 'true sink'. +/// +/// Writers are intended to be composable with one another. Many implementors +/// throughout [`std::io`] take and provide types which implement the `Write` +/// trait. +/// +/// [`write`]: Write::write +/// [`flush`]: Write::flush +/// [`std::io`]: self +/// +/// # Examples +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// fn main() -> std::io::Result<()> { +/// let data = b"some bytes"; +/// +/// let mut pos = 0; +/// let mut buffer = File::create("foo.txt")?; +/// +/// while pos < data.len() { +/// let bytes_written = buffer.write(&data[pos..])?; +/// pos += bytes_written; +/// } +/// Ok(()) +/// } +/// ``` +/// +/// The trait also provides convenience methods like [`write_all`], which calls +/// `write` in a loop until its entire input has been written. +/// +/// [`write_all`]: Write::write_all +pub trait Write { + /// Write a buffer into this writer, returning how many bytes were written. + /// + /// This function will attempt to write the entire contents of `buf`, but + /// the entire write may not succeed, or the write may also generate an + /// error. A call to `write` represents *at most one* attempt to write to + /// any wrapped object. + /// + /// Calls to `write` are not guaranteed to block waiting for data to be + /// written, and a write which would otherwise block can be indicated through + /// an [`Err`] variant. + /// + /// If the return value is [`Ok(n)`] then it must be guaranteed that + /// `n <= buf.len()`. A return value of `0` typically means that the + /// underlying object is no longer able to accept bytes and will likely not + /// be able to in the future as well, or that the buffer provided is empty. + /// + /// # Errors + /// + /// Each call to `write` may generate an I/O error indicating that the + /// operation could not be completed. If an error is returned then no bytes + /// in the buffer were written to this writer. + /// + /// It is **not** considered an error if the entire buffer could not be + /// written to this writer. + /// + /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the + /// write operation should be retried if there is nothing else to do. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// // Writes some prefix of the byte string, not necessarily all of it. + /// buffer.write(b"some bytes")?; + /// Ok(()) + /// } + /// ``` + /// + /// [`Ok(n)`]: Ok + fn write(&mut self, buf: &[u8]) -> Result; + + /// Flush this output stream, ensuring that all intermediately buffered + /// contents reach their destination. + /// + /// # Errors + /// + /// It is considered an error if not all bytes could be written due to + /// I/O errors or EOF being reached. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::io::BufWriter; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = BufWriter::new(File::create("foo.txt")?); + /// + /// buffer.write_all(b"some bytes")?; + /// buffer.flush()?; + /// Ok(()) + /// } + /// ``` + fn flush(&mut self) -> Result<()>; + + /// Attempts to write an entire buffer into this writer. + /// + /// This method will continuously call [`write`] until there is no more data + /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is + /// returned. This method will not return until the entire buffer has been + /// successfully written or such an error occurs. The first error that is + /// not of [`ErrorKind::Interrupted`] kind generated from this method will be + /// returned. + /// + /// If the buffer contains no data, this will never call [`write`]. + /// + /// # Errors + /// + /// This function will return the first error of + /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns. + /// + /// [`write`]: Write::write + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// buffer.write_all(b"some bytes")?; + /// Ok(()) + /// } + /// ``` + fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { + while !buf.is_empty() { + match self.write(buf) { + Ok(0) => { + return Err(Error::new( + ErrorKind::WriteZero, + "failed to write whole buffer", + )); + } + Ok(n) => buf = &buf[n..], + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } + /// Writes a formatted string into this writer, returning any error + /// encountered. + /// + /// This method is primarily used to interface with the + /// [`format_args!()`] macro, but it is rare that this should + /// explicitly be called. The [`write!()`] macro should be favored to + /// invoke this method instead. + /// + /// This function internally uses the [`write_all`] method on + /// this trait and hence will continuously write data so long as no errors + /// are received. This also means that partial writes are not indicated in + /// this signature. + /// + /// [`write_all`]: Write::write_all + /// + /// # Errors + /// + /// This function will return any I/O error reported while formatting. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// // this call + /// write!(buffer, "{:.*}", 2, 1.234567)?; + /// // turns into this: + /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; + /// Ok(()) + /// } + /// ``` + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { + // Create a shim which translates a Write to a fmt::Write and saves + // off I/O errors. instead of discarding them + struct Adaptor<'a, T: ?Sized + 'a> { + inner: &'a mut T, + error: Result<()>, + } + + impl fmt::Write for Adaptor<'_, T> { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.inner.write_all(s.as_bytes()) { + Ok(()) => Ok(()), + Err(e) => { + self.error = Err(e); + Err(fmt::Error) + } + } + } + } + + let mut output = Adaptor { + inner: self, + error: Ok(()), + }; + match fmt::write(&mut output, fmt) { + Ok(()) => Ok(()), + Err(..) => { + // check if the error came from the underlying `Write` or not + if output.error.is_err() { + output.error + } else { + Err(Error::new(ErrorKind::Other, "formatter error")) + } + } + } + } + + /// Creates a "by reference" adaptor for this instance of `Write`. + /// + /// The returned adaptor also implements `Write` and will simply borrow this + /// current writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::Write; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// let reference = buffer.by_ref(); + /// + /// // we can use reference just like our original buffer + /// reference.write_all(b"some bytes")?; + /// Ok(()) + /// } + /// ``` + fn by_ref(&mut self) -> &mut Self + where + Self: Sized, + { + self + } +} + +impl Write for &mut W { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + (**self).write(buf) + } + + #[inline] + fn flush(&mut self) -> Result<()> { + (**self).flush() + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + (**self).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { + (**self).write_fmt(fmt) + } +} + +/// Write is implemented for `&mut [u8]` by copying into the slice, overwriting +/// its data. +/// +/// Note that writing updates the slice to point to the yet unwritten part. +/// The slice will be empty when it has been completely overwritten. +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); + a.copy_from_slice(&data[..amt]); + *self = b; + Ok(amt) + } + + #[inline] + fn write_all(&mut self, data: &[u8]) -> Result<()> { + if self.write(data)? == data.len() { + Ok(()) + } else { + Err(Error::new( + ErrorKind::WriteZero, + "failed to write whole buffer", + )) + } + } + + #[inline] + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} + +/// Write is implemented for `Vec` by appending to the vector. +/// The vector will grow as needed. +impl Write for alloc::vec::Vec { + #[inline] + fn write(&mut self, buf: &[u8]) -> Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> Result<()> { + self.extend_from_slice(buf); + Ok(()) + } + + #[inline] + fn flush(&mut self) -> Result<()> { + Ok(()) + } +} diff --git a/borsh-rs/borsh/src/schema.rs b/borsh-rs/borsh/src/schema.rs index 689eea2a2..56665df92 100644 --- a/borsh-rs/borsh/src/schema.rs +++ b/borsh-rs/borsh/src/schema.rs @@ -13,8 +13,13 @@ #![allow(dead_code)] // Unclear why rust check complains on fields of `Definition` variants. use crate as borsh; // For `#[derive(BorshSerialize, BorshDeserialize)]`. use crate::{BorshDeserialize, BorshSchema as BorshSchemaMacro, BorshSerialize}; -use std::collections::hash_map::Entry; -use std::collections::*; +use crate::maybestd::{ + collections::{hash_map::Entry, HashMap}, + string::{ToString, String}, + vec::Vec, vec, + boxed::Box, + format +}; /// The type that we use to represent the declaration of the Borsh type. pub type Declaration = String; @@ -181,7 +186,7 @@ where } } -impl BorshSchema for std::result::Result +impl BorshSchema for core::result::Result where T: BorshSchema, E: BorshSchema, @@ -292,12 +297,13 @@ impl_tuple!( #[cfg(test)] mod tests { use super::*; + use crate::maybestd::collections::HashMap; macro_rules! map( - () => { ::std::collections::HashMap::new() }; + () => { HashMap::new() }; { $($key:expr => $value:expr),+ } => { { - let mut m = ::std::collections::HashMap::new(); + let mut m = HashMap::new(); $( m.insert($key.to_string(), $value); )+ diff --git a/borsh-rs/borsh/src/schema_helpers.rs b/borsh-rs/borsh/src/schema_helpers.rs index 6ed828177..92435a257 100644 --- a/borsh-rs/borsh/src/schema_helpers.rs +++ b/borsh-rs/borsh/src/schema_helpers.rs @@ -1,15 +1,18 @@ +use crate::maybestd::{ + io::{Error, ErrorKind, Result}, + vec::Vec +}; use crate::schema::BorshSchemaContainer; use crate::{BorshDeserialize, BorshSchema, BorshSerialize}; -use std::io; /// 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 /// correct. -pub fn try_from_slice_with_schema(v: &[u8]) -> io::Result { +pub fn try_from_slice_with_schema(v: &[u8]) -> Result { let (schema, object) = <(BorshSchemaContainer, T)>::try_from_slice(v)?; if T::schema_container() != schema { - return Err(io::Error::new( - io::ErrorKind::InvalidData, + return Err(Error::new( + ErrorKind::InvalidData, "Borsh schema does not match", )); } @@ -18,7 +21,7 @@ pub fn try_from_slice_with_schema(v: &[u8]) - /// Serialize object into a vector of bytes and prefix with the schema serialized as vector of /// bytes in Borsh format. -pub fn try_to_vec_with_schema(value: &T) -> io::Result> { +pub fn try_to_vec_with_schema(value: &T) -> Result> { let schema = T::schema_container(); let mut res = schema.try_to_vec()?; res.extend(value.try_to_vec()?); diff --git a/borsh-rs/borsh/src/ser/mod.rs b/borsh-rs/borsh/src/ser/mod.rs index f915927df..dfdbe5688 100644 --- a/borsh-rs/borsh/src/ser/mod.rs +++ b/borsh-rs/borsh/src/ser/mod.rs @@ -1,17 +1,23 @@ -use std::borrow::Cow; -use std::collections::{BTreeMap, HashMap, HashSet}; -use std::convert::TryFrom; -use std::mem::size_of; -use std::{io, io::Write}; +use core::convert::TryFrom; +use core::mem::size_of; + +use crate::maybestd::{ + io::{ErrorKind, Result, Write}, + collections::{HashMap, HashSet}, + borrow::{ToOwned, Cow}, + string::String, + boxed::Box, + vec::Vec +}; const DEFAULT_SERIALIZER_CAPACITY: usize = 1024; /// A data-structure that can be serialized into binary format by NBOR. pub trait BorshSerialize { - fn serialize(&self, writer: &mut W) -> io::Result<()>; + fn serialize(&self, writer: &mut W) -> Result<()>; /// Serialize this instance into a vector of bytes. - fn try_to_vec(&self) -> io::Result> { + fn try_to_vec(&self) -> Result> { let mut result = Vec::with_capacity(DEFAULT_SERIALIZER_CAPACITY); self.serialize(&mut result)?; Ok(result) @@ -30,8 +36,8 @@ pub trait BorshSerialize { impl BorshSerialize for u8 { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { - writer.write_all(std::slice::from_ref(self)) + fn serialize(&self, writer: &mut W) -> Result<()> { + writer.write_all(core::slice::from_ref(self)) } #[inline] @@ -44,8 +50,9 @@ macro_rules! impl_for_integer { ($type: ident) => { impl BorshSerialize for $type { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { - writer.write_all(&self.to_le_bytes()) + fn serialize(&self, writer: &mut W) -> Result<()> { + let bytes = self.to_le_bytes(); + writer.write_all(&bytes) } } }; @@ -67,7 +74,7 @@ macro_rules! impl_for_float { ($type: ident) => { impl BorshSerialize for $type { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { assert!( !self.is_nan(), "For portability reasons we do not allow to serialize NaNs." @@ -83,7 +90,7 @@ impl_for_float!(f64); impl BorshSerialize for bool { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { (if *self { 1u8 } else { 0u8 }).serialize(writer) } } @@ -93,7 +100,7 @@ where T: BorshSerialize, { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { match self { None => 0u8.serialize(writer), Some(value) => { @@ -104,13 +111,13 @@ where } } -impl BorshSerialize for std::result::Result +impl BorshSerialize for core::result::Result where T: BorshSerialize, E: BorshSerialize, { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { match self { Err(e) => { 0u8.serialize(writer)?; @@ -126,14 +133,14 @@ where impl BorshSerialize for str { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { self.as_bytes().serialize(writer) } } impl BorshSerialize for String { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { self.as_bytes().serialize(writer) } } @@ -143,16 +150,16 @@ where T: BorshSerialize, { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { writer.write_all( - &(u32::try_from(self.len()).map_err(|_| io::ErrorKind::InvalidInput)?).to_le_bytes(), + &(u32::try_from(self.len()).map_err(|_| ErrorKind::InvalidInput)?).to_le_bytes(), )?; if T::is_u8() && size_of::() == size_of::() { // The code below uses unsafe memory representation from `&[T]` to `&[u8]`. // The size of the memory should match because `size_of::() == size_of::()`. // // `T::is_u8()` is a workaround for not being able to implement `Vec` separately. - let buf = unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) }; + let buf = unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) }; writer.write_all(buf)?; } else { for item in self { @@ -165,63 +172,42 @@ where impl BorshSerialize for &T { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { (*self).serialize(writer) } } impl BorshSerialize for Cow<'_, T> where - T: BorshSerialize + std::borrow::ToOwned + ?Sized, + T: BorshSerialize + ToOwned + ?Sized, { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { self.as_ref().serialize(writer) } } -#[cfg(feature = "std")] impl BorshSerialize for Vec where T: BorshSerialize, { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { self.as_slice().serialize(writer) } } -#[cfg(feature = "std")] -impl BorshSerialize for HashSet -where - T: BorshSerialize + PartialOrd, -{ - #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { - let mut vec = self.iter().collect::>(); - vec.sort_by(|a, b| a.partial_cmp(b).unwrap()); - u32::try_from(vec.len()) - .map_err(|_| io::ErrorKind::InvalidInput)? - .serialize(writer)?; - for item in vec { - item.serialize(writer)?; - } - Ok(()) - } -} - -#[cfg(feature = "std")] impl BorshSerialize for HashMap where K: BorshSerialize + PartialOrd, V: BorshSerialize, { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { let mut vec = self.iter().collect::>(); vec.sort_by(|(a, _), (b, _)| a.partial_cmp(b).unwrap()); u32::try_from(vec.len()) - .map_err(|_| io::ErrorKind::InvalidInput)? + .map_err(|_| ErrorKind::InvalidInput)? .serialize(writer)?; for (key, value) in vec { key.serialize(writer)?; @@ -231,29 +217,30 @@ where } } -#[cfg(feature = "std")] -impl BorshSerialize for BTreeMap -where - K: BorshSerialize + PartialOrd, - V: BorshSerialize, + +impl BorshSerialize for HashSet + where + T: BorshSerialize + PartialOrd, { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { - u32::try_from(self.len()) - .map_err(|_| io::ErrorKind::InvalidInput)? + fn serialize(&self, writer: &mut W) -> Result<()> { + let mut vec = self.iter().collect::>(); + vec.sort_by(|a, b| a.partial_cmp(b).unwrap()); + u32::try_from(vec.len()) + .map_err(|_| ErrorKind::InvalidInput)? .serialize(writer)?; - for (key, value) in self.iter() { - key.serialize(writer)?; - value.serialize(writer)?; + for item in vec { + item.serialize(writer)?; } Ok(()) } } + #[cfg(feature = "std")] impl BorshSerialize for std::net::SocketAddr { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { match *self { std::net::SocketAddr::V4(ref addr) => { 0u8.serialize(writer)?; @@ -270,7 +257,7 @@ impl BorshSerialize for std::net::SocketAddr { #[cfg(feature = "std")] impl BorshSerialize for std::net::SocketAddrV4 { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { self.ip().serialize(writer)?; self.port().serialize(writer) } @@ -279,7 +266,7 @@ impl BorshSerialize for std::net::SocketAddrV4 { #[cfg(feature = "std")] impl BorshSerialize for std::net::SocketAddrV6 { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { self.ip().serialize(writer)?; self.port().serialize(writer) } @@ -288,7 +275,7 @@ impl BorshSerialize for std::net::SocketAddrV6 { #[cfg(feature = "std")] impl BorshSerialize for std::net::Ipv4Addr { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { writer.write_all(&self.octets()) } } @@ -296,13 +283,13 @@ impl BorshSerialize for std::net::Ipv4Addr { #[cfg(feature = "std")] impl BorshSerialize for std::net::Ipv6Addr { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { writer.write_all(&self.octets()) } } impl BorshSerialize for Box { - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { self.as_ref().serialize(writer) } } @@ -314,13 +301,13 @@ macro_rules! impl_arrays { where T: BorshSerialize { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { if T::is_u8() && size_of::() == size_of::() { // The code below uses unsafe memory representation from `&[T]` to `&[u8]`. // The size of the memory should match because `size_of::() == size_of::()`. // // `T::is_u8()` is a workaround for not being able to implement `[u8; *]` separately. - let buf = unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) }; + let buf = unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) }; writer.write_all(buf)?; } else { for el in self.iter() { @@ -339,7 +326,7 @@ where T: BorshSerialize, { #[inline] - fn serialize(&self, _writer: &mut W) -> io::Result<()> { + fn serialize(&self, _writer: &mut W) -> Result<()> { Ok(()) } } @@ -347,7 +334,7 @@ where impl_arrays!(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 64 65 128 256 512 1024 2048); impl BorshSerialize for () { - fn serialize(&self, _writer: &mut W) -> io::Result<()> { + fn serialize(&self, _writer: &mut W) -> Result<()> { Ok(()) } } @@ -358,7 +345,7 @@ macro_rules! impl_tuple { where $($name: BorshSerialize,)+ { #[inline] - fn serialize(&self, writer: &mut W) -> io::Result<()> { + fn serialize(&self, writer: &mut W) -> Result<()> { $(self.$idx.serialize(writer)?;)+ Ok(()) } diff --git a/borsh-rs/borsh/tests/test_schema_enums.rs b/borsh-rs/borsh/tests/test_schema_enums.rs index 2060e2494..c7ad0f622 100644 --- a/borsh-rs/borsh/tests/test_schema_enums.rs +++ b/borsh-rs/borsh/tests/test_schema_enums.rs @@ -1,12 +1,13 @@ #![allow(dead_code)] // Local structures do not have their fields used. use borsh::schema::*; use borsh::schema_helpers::{try_from_slice_with_schema, try_to_vec_with_schema}; +use borsh::maybestd::collections::HashMap; macro_rules! map( - () => { ::std::collections::HashMap::new() }; + () => { HashMap::new() }; { $($key:expr => $value:expr),+ } => { { - let mut m = ::std::collections::HashMap::new(); + let mut m = HashMap::new(); $( m.insert($key.to_string(), $value); )+ diff --git a/borsh-rs/borsh/tests/test_schema_nested.rs b/borsh-rs/borsh/tests/test_schema_nested.rs index c3a7e612b..d003eb900 100644 --- a/borsh-rs/borsh/tests/test_schema_nested.rs +++ b/borsh-rs/borsh/tests/test_schema_nested.rs @@ -1,11 +1,12 @@ #![allow(dead_code)] // Local structures do not have their fields used. use borsh::schema::*; +use borsh::maybestd::collections::HashMap; macro_rules! map( - () => { ::std::collections::HashMap::new() }; + () => { HashMap::new() }; { $($key:expr => $value:expr),+ } => { { - let mut m = ::std::collections::HashMap::new(); + let mut m = HashMap::new(); $( m.insert($key.to_string(), $value); )+ @@ -23,7 +24,7 @@ pub fn duplicated_instantiations() { struct Cucumber; #[derive(borsh::BorshSchema)] struct Oil { - seeds: std::collections::HashMap, + seeds: HashMap, liquid: Option, }; #[derive(borsh::BorshSchema)] diff --git a/borsh-rs/borsh/tests/test_schema_structs.rs b/borsh-rs/borsh/tests/test_schema_structs.rs index 350feb2a4..5fa894380 100644 --- a/borsh-rs/borsh/tests/test_schema_structs.rs +++ b/borsh-rs/borsh/tests/test_schema_structs.rs @@ -1,10 +1,11 @@ use borsh::schema::*; +use borsh::maybestd::collections::HashMap; macro_rules! map( - () => { ::std::collections::HashMap::new() }; + () => { HashMap::new() }; { $($key:expr => $value:expr),+ } => { { - let mut m = ::std::collections::HashMap::new(); + let mut m = HashMap::new(); $( m.insert($key.to_string(), $value); )+ @@ -105,7 +106,7 @@ pub fn tuple_struct_params() { pub fn simple_generics() { #[derive(borsh::BorshSchema)] struct A { - _f1: std::collections::HashMap, + _f1: HashMap, _f2: String, }; assert_eq!( diff --git a/borsh-rs/borsh/tests/test_simple_structs.rs b/borsh-rs/borsh/tests/test_simple_structs.rs index ef1ecbb1b..3e3262ee5 100644 --- a/borsh-rs/borsh/tests/test_simple_structs.rs +++ b/borsh-rs/borsh/tests/test_simple_structs.rs @@ -1,5 +1,5 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use std::collections::{HashMap, HashSet}; +use borsh::maybestd::collections::{HashMap, HashSet}; #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)] #[borsh_init(init)]