Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add implicit BorshSchema derive for store::UnorderedMap #1209

Merged
merged 5 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ env:
jobs:
test:
runs-on: ${{ matrix.platform.os }}
name: "${{ matrix.platform.os }} ${{ matrix.platform.rs }}"
name: "${{ matrix.platform.os }} ${{ matrix.platform.rs }} ${{ matrix.features }}"
strategy:
matrix:
platform:
Expand All @@ -21,6 +21,7 @@ jobs:
rs: 1.76.0
- os: macos-latest
rs: 1.78.0
features: ['', '--features unstable,legacy,__abi-generate']
steps:
- uses: actions/checkout@v3
- name: "${{ matrix.platform.rs }} with rustfmt, and wasm32"
Expand All @@ -38,7 +39,7 @@ jobs:
- name: print rustc && rustdoc version
run: rustc --version && rustdoc --version
- name: test
run: cargo test --all --features unstable,legacy
run: cargo test --all ${{ matrix.features }}
lint:
name: Clippy and fmt
runs-on: ubuntu-latest
Expand Down Expand Up @@ -68,7 +69,7 @@ jobs:
default: true
- uses: Swatinem/rust-cache@v1
- name: Compilation tests
run: cargo test --package near-sdk --test compilation_tests --features abi --features unstable -- compilation_tests --exact --nocapture
run: cargo test --package near-sdk --test compilation_tests --features __abi-generate --features unstable -- compilation_tests --exact --nocapture
windows:
name: Windows
runs-on: windows-latest
Expand Down
4 changes: 3 additions & 1 deletion near-sdk-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,8 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream {
#[automatically_derived]
impl #generics #near_sdk_crate::schemars::JsonSchema for #input_ident_proxy #generics #where_clause {
fn schema_name() -> ::std::string::String {
// TODO: consider replacing with
// <#input_ident #generics as #near_sdk_crate::schemars::JsonSchema>::schema_name()
stringify!(#input_ident #generics).to_string()
}

Expand All @@ -671,7 +673,7 @@ pub fn derive_near_schema(#[allow(unused)] input: TokenStream) -> TokenStream {
#[automatically_derived]
impl #generics #near_sdk_crate::borsh::BorshSchema for #input_ident_proxy #generics #where_clause {
fn declaration() -> #near_sdk_crate::borsh::schema::Declaration {
stringify!(#input_ident #generics).to_string()
<#input_ident #generics as #near_sdk_crate::borsh::BorshSchema>::declaration()
}

fn add_definitions_recursively(
Expand Down
8 changes: 5 additions & 3 deletions near-sdk/compilation_tests/all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ fn compilation_tests() {
t.pass("compilation_tests/init_function.rs");
t.pass("compilation_tests/init_ignore_state.rs");
t.pass("compilation_tests/no_default.rs");
// TODO: unignore upon resolution of https://github.com/near/near-sdk-rs/issues/1211
// t.pass("compilation_tests/lifetime_method_result.rs");
t.pass("compilation_tests/lifetime_method.rs");
t.pass("compilation_tests/cond_compilation.rs");
t.compile_fail("compilation_tests/payable_view.rs");
Expand All @@ -21,9 +23,9 @@ fn compilation_tests() {
t.pass("compilation_tests/function_error.rs");
t.pass("compilation_tests/enum_near_bindgen.rs");
t.pass("compilation_tests/schema_derive.rs");
if rustversion::cfg!(since(1.72)) {
// The compilation error output has slightly changed in 1.72, so we
// snapshoted this new version
if rustversion::cfg!(since(1.78)) && std::env::consts::OS == "linux" {
// The compilation error output has slightly changed in 1.7x and between platforms,
// so we snapshoted this single version
t.compile_fail("compilation_tests/schema_derive_invalids.rs");
}
t.compile_fail("compilation_tests/generic_function.rs");
Expand Down
4 changes: 2 additions & 2 deletions near-sdk/compilation_tests/lifetime_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ struct Ident {

#[near]
impl Ident {
pub fn is_ident<'a>(&self, other: &'a u32) -> Option<&'a u32> {
pub fn is_ident<'a>(&self, other: &'a u32) -> Option<u32> {
if *other == self.value {
Some(other)
Some(*other)
} else {
None
}
Expand Down
22 changes: 22 additions & 0 deletions near-sdk/compilation_tests/lifetime_method_result.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! Method signature uses lifetime.

use near_sdk::near;

#[near(contract_state)]
#[derive(Default)]
struct Ident {
value: u32,
}

#[near]
impl Ident {
pub fn is_ident<'a>(&self, other: &'a u32) -> Option<&'a u32> {
if *other == self.value {
Some(other)
} else {
None
}
}
}

fn main() {}
148 changes: 143 additions & 5 deletions near-sdk/src/store/unordered_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,26 @@ 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)]
#[near(inside_nearsdk)]
pub struct UnorderedMap<K, V, H = Sha256>
where
K: BorshSerialize + Ord,
V: BorshSerialize,
H: ToKey,
{
// ser/de is independent of `K` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed
#[borsh(bound(serialize = "", 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 = ""))
)]
keys: FreeList<K>,
// ser/de is independent of `K`, `V`, `H` ser/de, `BorshSerialize`/`BorshDeserialize` bounds removed
#[borsh(bound(serialize = "", deserialize = ""))]
// ser/de is independent of `K`, `V`, `H` 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: LookupMap<K, ValueAndIndex<V>, H>,
}

Expand Down Expand Up @@ -841,4 +849,134 @@ mod tests {
assert_eq!(map.remove_entry(&1).unwrap(), (1, 1));
assert_eq!(map.remove_entry(&3).unwrap(), (3, 3));
}

#[allow(unused)]
macro_rules! schema_map(
() => { BTreeMap::new() };
{ $($key:expr => $value:expr),+ } => {
{
let mut m = BTreeMap::new();
$(
m.insert($key.to_string(), $value);
)+
m
}
};
);

#[cfg(feature = "abi")]
#[test]
fn test_borsh_schema() {
use borsh::schema::{Definition, Fields};
use std::collections::BTreeMap;

#[derive(
borsh::BorshSerialize, borsh::BorshDeserialize, PartialEq, Eq, PartialOrd, Ord,
)]
struct NoSchemaStruct;

assert_eq!(
"UnorderedMap".to_string(),
<UnorderedMap<NoSchemaStruct, NoSchemaStruct> as borsh::BorshSchema>::declaration()
);
let mut defs = Default::default();
<UnorderedMap<NoSchemaStruct, NoSchemaStruct> as borsh::BorshSchema>::add_definitions_recursively(&mut defs);
println!("{:#?}", defs);
assert_eq!(
schema_map! {
"UnorderedMap" => Definition::Struct {
fields: Fields::NamedFields(vec![
(
"keys".to_string(),
"FreeList".to_string(),
),
(
"values".to_string(),
"LookupMap".to_string(),
),
]
)},
"FreeList" => Definition::Struct {
fields: Fields::NamedFields(vec![
(
"first_free".to_string(),
"Option<FreeListIndex>".to_string(),
),
(
"occupied_count".to_string(),
"u32".to_string(),
),
(
"elements".to_string(),
"Vector".to_string(),
),
]
)},
"Option<FreeListIndex>" => Definition::Enum {
tag_width: 1,
variants: vec![
(
0,
"None".to_string(),
"()".to_string(),
),
(
1,
"Some".to_string(),
"FreeListIndex".to_string(),
),
]},
"()" => Definition::Primitive(0),
"FreeListIndex" => Definition::Struct {
fields: Fields::UnnamedFields(
vec![
"u32".to_string(),
],
),
},
"u32" => Definition::Primitive(4 ),
"Vector" => Definition::Struct {
fields: Fields::NamedFields(
vec![
(
"len".to_string(),
"u32".to_string(),
),
(
"values".to_string(),
"IndexMap".to_string(),
),
],
),
},
"IndexMap" => Definition::Struct {
fields: Fields::NamedFields(
vec![
(
"prefix".to_string(),
"Vec<u8>".to_string(),
),
],
),
},
"Vec<u8>" => Definition::Sequence {
length_width: 4,
length_range: 0..=4294967295,
elements: "u8".to_string(),
},
"u8" => Definition::Primitive(1),
"LookupMap" => Definition::Struct {
fields: Fields::NamedFields(
vec![
(
"prefix".to_string(),
"Vec<u8>".to_string(),
),
],
),
}
},
defs
);
}
}
Loading