diff --git a/near-sdk/compilation_tests/schema_derive_invalids.stderr b/near-sdk/compilation_tests/schema_derive_invalids.stderr index dc89e2d36..ceb7c3037 100644 --- a/near-sdk/compilation_tests/schema_derive_invalids.stderr +++ b/near-sdk/compilation_tests/schema_derive_invalids.stderr @@ -87,7 +87,7 @@ error[E0277]: the trait bound `Inner: JsonSchema` is not satisfied i128 and $N others note: required by a bound in `SchemaGenerator::subschema_for` - --> $CARGO/schemars-0.8.16/src/gen.rs + --> $CARGO/schemars-0.8.17/src/gen.rs | | pub fn subschema_for(&mut self) -> Schema { | ^^^^^^^^^^ required by this bound in `SchemaGenerator::subschema_for` diff --git a/near-sdk/src/collections/legacy_tree_map.rs b/near-sdk/src/collections/legacy_tree_map.rs index e532a6214..17ed91314 100644 --- a/near-sdk/src/collections/legacy_tree_map.rs +++ b/near-sdk/src/collections/legacy_tree_map.rs @@ -25,7 +25,19 @@ use crate::IntoStorageKey; #[near(inside_nearsdk)] pub struct LegacyTreeMap { root: u64, + // ser/de is independent of `K`,`V` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] val: UnorderedMap, + // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] tree: Vector>, } diff --git a/near-sdk/src/collections/tree_map.rs b/near-sdk/src/collections/tree_map.rs index 82ab4f40a..efeda40b2 100644 --- a/near-sdk/src/collections/tree_map.rs +++ b/near-sdk/src/collections/tree_map.rs @@ -19,7 +19,19 @@ use near_sdk_macros::near; #[near(inside_nearsdk)] pub struct TreeMap { root: u64, + // ser/de is independent of `K`,`V` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] val: LookupMap, + // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] tree: Vector>, } diff --git a/near-sdk/src/collections/unordered_map/mod.rs b/near-sdk/src/collections/unordered_map/mod.rs index facc17e58..c59101bc0 100644 --- a/near-sdk/src/collections/unordered_map/mod.rs +++ b/near-sdk/src/collections/unordered_map/mod.rs @@ -19,7 +19,19 @@ const ERR_VALUE_SERIALIZATION: &str = "Cannot serialize value with Borsh"; #[near(inside_nearsdk)] pub struct UnorderedMap { key_index_prefix: Vec, + // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] keys: Vector, + // ser/de is independent of `V` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] values: Vector, } diff --git a/near-sdk/src/collections/unordered_set.rs b/near-sdk/src/collections/unordered_set.rs index b6abb2b47..119cf089a 100644 --- a/near-sdk/src/collections/unordered_set.rs +++ b/near-sdk/src/collections/unordered_set.rs @@ -13,6 +13,12 @@ const ERR_ELEMENT_SERIALIZATION: &str = "Cannot serialize element with Borsh"; #[near(inside_nearsdk)] pub struct UnorderedSet { element_index_prefix: Vec, + // ser/de is independent of `T` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] elements: Vector, } diff --git a/near-sdk/src/store/free_list/mod.rs b/near-sdk/src/store/free_list/mod.rs index 0903c49c4..10cf36442 100644 --- a/near-sdk/src/store/free_list/mod.rs +++ b/near-sdk/src/store/free_list/mod.rs @@ -17,7 +17,7 @@ pub struct FreeListIndex(pub(crate) u32); /// Unordered container of values. This is similar to [`Vector`] except that values are not /// re-arranged on removal, keeping the indices consistent. When an element is removed, it will /// be replaced with an empty cell which will be populated on the next insertion. -#[derive(NearSchema)] +#[derive(NearSchema, BorshSerialize, BorshDeserialize)] #[inside_nearsdk] #[abi(borsh)] pub(crate) struct FreeList @@ -26,36 +26,15 @@ where { first_free: Option, occupied_count: u32, + // ser/de is independent of `T` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] elements: Vector>, } -//? Manual implementations needed only because borsh derive is leaking field types -// https://github.com/near/borsh-rs/issues/41 -impl BorshSerialize for FreeList -where - T: BorshSerialize, -{ - fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { - BorshSerialize::serialize(&self.first_free, writer)?; - BorshSerialize::serialize(&self.occupied_count, writer)?; - BorshSerialize::serialize(&self.elements, writer)?; - Ok(()) - } -} - -impl BorshDeserialize for FreeList -where - T: BorshSerialize, -{ - fn deserialize_reader(reader: &mut R) -> Result { - Ok(Self { - first_free: BorshDeserialize::deserialize_reader(reader)?, - occupied_count: BorshDeserialize::deserialize_reader(reader)?, - elements: BorshDeserialize::deserialize_reader(reader)?, - }) - } -} - #[near(inside_nearsdk)] #[derive(Debug)] enum Slot { diff --git a/near-sdk/src/store/index_map.rs b/near-sdk/src/store/index_map.rs index 0b4e756dd..2a37bc287 100644 --- a/near-sdk/src/store/index_map.rs +++ b/near-sdk/src/store/index_map.rs @@ -22,7 +22,7 @@ where /// /// Note: u32 indices are used over usize to have consistent functionality across architectures. /// Some functionality would be different from tests to Wasm if exceeding 32-bit length. - #[borsh(skip, bound(deserialize = ""))] + #[borsh(skip, bound(deserialize = ""))] // removes `core::default::Default` bound from T pub(crate) cache: StableMap>>, } diff --git a/near-sdk/src/store/iterable_map/mod.rs b/near-sdk/src/store/iterable_map/mod.rs index 31471a277..f1642a2ff 100644 --- a/near-sdk/src/store/iterable_map/mod.rs +++ b/near-sdk/src/store/iterable_map/mod.rs @@ -81,6 +81,7 @@ use super::{LookupMap, ERR_INCONSISTENT_STATE, ERR_NOT_EXIST}; /// ``` /// /// [`with_hasher`]: Self::with_hasher +#[derive(BorshDeserialize, BorshSerialize)] pub struct IterableMap where K: BorshSerialize + Ord, @@ -91,7 +92,12 @@ where // not skipping empty/unoccupied entries white trying to get to the next element. // See https://github.com/near/near-sdk-rs/issues/1134 to understand the difference between // `store::UnorderedMap` and `store::IterableMap`. + + // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed + #[borsh(bound(serialize = "", deserialize = ""))] keys: Vector, + // ser/de is independent of `K`, `V`, `H` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed + #[borsh(bound(serialize = "", deserialize = ""))] values: LookupMap, H>, } @@ -101,35 +107,6 @@ struct ValueAndIndex { key_index: u32, } -//? Manual implementations needed only because borsh derive is leaking field types -// https://github.com/near/borsh-rs/issues/41 -impl BorshSerialize for IterableMap -where - K: BorshSerialize + Ord, - V: BorshSerialize, - H: ToKey, -{ - fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { - BorshSerialize::serialize(&self.keys, writer)?; - BorshSerialize::serialize(&self.values, writer)?; - Ok(()) - } -} - -impl BorshDeserialize for IterableMap -where - K: BorshSerialize + Ord, - V: BorshSerialize, - H: ToKey, -{ - fn deserialize_reader(reader: &mut R) -> Result { - Ok(Self { - keys: BorshDeserialize::deserialize_reader(reader)?, - values: BorshDeserialize::deserialize_reader(reader)?, - }) - } -} - impl Drop for IterableMap where K: BorshSerialize + Ord, diff --git a/near-sdk/src/store/lazy/mod.rs b/near-sdk/src/store/lazy/mod.rs index 87e544d22..0bd6f5f63 100644 --- a/near-sdk/src/store/lazy/mod.rs +++ b/near-sdk/src/store/lazy/mod.rs @@ -68,7 +68,7 @@ where { /// Key bytes to index the contract's storage. storage_key: Box<[u8]>, - #[borsh(skip, bound(deserialize = ""))] + #[borsh(skip, bound(deserialize = ""))] // removes `core::default::Default` bound from T /// Cached value which is lazily loaded and deserialized from storage. cache: OnceCell>, } diff --git a/near-sdk/src/store/lazy_option/mod.rs b/near-sdk/src/store/lazy_option/mod.rs index 8591f9e09..274efcaa7 100644 --- a/near-sdk/src/store/lazy_option/mod.rs +++ b/near-sdk/src/store/lazy_option/mod.rs @@ -41,7 +41,7 @@ where prefix: Box<[u8]>, /// Cached value which is lazily loaded and deserialized from storage. - #[borsh(skip, bound(deserialize = ""))] + #[borsh(skip, bound(deserialize = ""))] // removes `core::default::Default` bound from T cache: OnceCell>, } diff --git a/near-sdk/src/store/lookup_map/mod.rs b/near-sdk/src/store/lookup_map/mod.rs index a07658c6f..012d603c6 100644 --- a/near-sdk/src/store/lookup_map/mod.rs +++ b/near-sdk/src/store/lookup_map/mod.rs @@ -88,7 +88,7 @@ where /// Cache for loads and intermediate changes to the underlying vector. /// The cached entries are wrapped in a [`Box`] to avoid existing pointers from being /// invalidated. - #[borsh(skip, bound(deserialize = ""))] + #[borsh(skip, bound(deserialize = ""))] // removes `core::default::Default` from `K`/`V` cache: StableMap>, } diff --git a/near-sdk/src/store/tree_map/mod.rs b/near-sdk/src/store/tree_map/mod.rs index b18d67b28..dfa85209f 100644 --- a/near-sdk/src/store/tree_map/mod.rs +++ b/near-sdk/src/store/tree_map/mod.rs @@ -30,13 +30,18 @@ fn expect(val: Option) -> T { /// - `min`/`max`: O(log(N)) /// - `above`/`below`: O(log(N)) /// - `range` of K elements: O(Klog(N)) +#[derive(BorshDeserialize, BorshSerialize)] pub struct TreeMap where K: BorshSerialize + Ord, V: BorshSerialize, H: ToKey, { + // ser/de is independent of `K`, `V`, `H` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed + #[borsh(bound(serialize = "", deserialize = ""))] values: LookupMap, + // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed + #[borsh(bound(serialize = "", deserialize = ""))] tree: Tree, } @@ -65,42 +70,18 @@ where } } -//? Manual implementations needed only because borsh derive is leaking field types -// https://github.com/near/borsh-rs/issues/41 -impl BorshSerialize for TreeMap -where - K: BorshSerialize + Ord, - V: BorshSerialize, - H: ToKey, -{ - fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { - BorshSerialize::serialize(&self.values, writer)?; - BorshSerialize::serialize(&self.tree, writer)?; - Ok(()) - } -} - -impl BorshDeserialize for TreeMap -where - K: BorshSerialize + Ord, - V: BorshSerialize, - H: ToKey, -{ - fn deserialize_reader(reader: &mut R) -> Result { - Ok(Self { - values: BorshDeserialize::deserialize_reader(reader)?, - tree: BorshDeserialize::deserialize_reader(reader)?, - }) - } -} - #[near(inside_nearsdk)] struct Tree where K: BorshSerialize, { root: Option, - #[borsh(bound(deserialize = ""))] + // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] nodes: FreeList>, } diff --git a/near-sdk/src/store/unordered_map/mod.rs b/near-sdk/src/store/unordered_map/mod.rs index c99852f25..c47f18b1b 100644 --- a/near-sdk/src/store/unordered_map/mod.rs +++ b/near-sdk/src/store/unordered_map/mod.rs @@ -90,13 +90,18 @@ use super::{FreeList, LookupMap, ERR_INCONSISTENT_STATE, ERR_NOT_EXIST}; since = "5.0.0", note = "Suboptimal iteration performance. See performance considerations doc for details." )] +#[derive(BorshDeserialize, BorshSerialize)] pub struct UnorderedMap where K: BorshSerialize + Ord, V: BorshSerialize, H: ToKey, { + // ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed + #[borsh(bound(serialize = "", deserialize = ""))] keys: FreeList, + // ser/de is independent of `K`, `V`, `H` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed + #[borsh(bound(serialize = "", deserialize = ""))] values: LookupMap, H>, } @@ -106,35 +111,6 @@ struct ValueAndIndex { key_index: FreeListIndex, } -//? Manual implementations needed only because borsh derive is leaking field types -// https://github.com/near/borsh-rs/issues/41 -impl BorshSerialize for UnorderedMap -where - K: BorshSerialize + Ord, - V: BorshSerialize, - H: ToKey, -{ - fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { - BorshSerialize::serialize(&self.keys, writer)?; - BorshSerialize::serialize(&self.values, writer)?; - Ok(()) - } -} - -impl BorshDeserialize for UnorderedMap -where - K: BorshSerialize + Ord, - V: BorshSerialize, - H: ToKey, -{ - fn deserialize_reader(reader: &mut R) -> Result { - Ok(Self { - keys: BorshDeserialize::deserialize_reader(reader)?, - values: BorshDeserialize::deserialize_reader(reader)?, - }) - } -} - impl Drop for UnorderedMap where K: BorshSerialize + Ord, diff --git a/near-sdk/src/store/unordered_set/mod.rs b/near-sdk/src/store/unordered_set/mod.rs index a1d266d57..3964bff2f 100644 --- a/near-sdk/src/store/unordered_set/mod.rs +++ b/near-sdk/src/store/unordered_set/mod.rs @@ -97,8 +97,10 @@ where T: BorshSerialize + Ord, H: ToKey, { + // ser/de is independent of `T` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed #[borsh(bound(serialize = "", deserialize = ""))] elements: FreeList, + // ser/de is independent of `T`, `H` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed #[borsh(bound(serialize = "", deserialize = ""))] index: LookupMap, } diff --git a/near-sdk/src/store/vec/mod.rs b/near-sdk/src/store/vec/mod.rs index fbdfdcc49..8703d7ee4 100644 --- a/near-sdk/src/store/vec/mod.rs +++ b/near-sdk/src/store/vec/mod.rs @@ -112,7 +112,7 @@ fn expect_consistent_state(val: Option) -> T { /// vec.extend([1, 2, 3].iter().copied()); /// assert!(Iterator::eq(vec.into_iter(), [7, 1, 2, 3].iter())); /// ``` -#[derive(NearSchema)] +#[derive(NearSchema, BorshSerialize, BorshDeserialize)] #[inside_nearsdk] #[abi(borsh)] pub struct Vector @@ -120,34 +120,15 @@ where T: BorshSerialize, { pub(crate) len: u32, + // ser/de is independent of `T` ser/de, `BorshSerialize`/`BorshDeserialize`/`BorshSchema` bounds removed + #[cfg_attr(not(feature = "abi"), borsh(bound(serialize = "", deserialize = "")))] + #[cfg_attr( + feature = "abi", + borsh(bound(serialize = "", deserialize = ""), schema(params = "")) + )] pub(crate) values: IndexMap, } -//? Manual implementations needed only because borsh derive is leaking field types -// https://github.com/near/borsh-rs/issues/41 -impl BorshSerialize for Vector -where - T: BorshSerialize, -{ - fn serialize(&self, writer: &mut W) -> Result<(), std::io::Error> { - BorshSerialize::serialize(&self.len, writer)?; - BorshSerialize::serialize(&self.values, writer)?; - Ok(()) - } -} - -impl BorshDeserialize for Vector -where - T: BorshSerialize, -{ - fn deserialize_reader(reader: &mut R) -> Result { - Ok(Self { - len: BorshDeserialize::deserialize_reader(reader)?, - values: BorshDeserialize::deserialize_reader(reader)?, - }) - } -} - #[test] fn collections_vec_not_backwards_compatible() { use crate::collections::Vector as Vec1;