diff --git a/Cargo.lock b/Cargo.lock index 59e2ed1a0e..9f1f2dd7bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -495,9 +495,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.49" +version = "1.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" dependencies = [ "find-msvc-tools", "shlex", @@ -1088,18 +1088,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", @@ -2122,6 +2122,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -2147,6 +2156,17 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "serde", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -2563,9 +2583,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" [[package]] name = "jiff" @@ -2742,9 +2762,9 @@ checksum = "0c6639b70a7ce854b79c70d7e83f16b5dc0137cc914f3d7d03803b513ecc67ac" [[package]] name = "libz-rs-sys" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15413ef615ad868d4d65dce091cb233b229419c7c0c4bcaa746c0901c49ff39c" +checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415" dependencies = [ "zlib-rs", ] @@ -3145,6 +3165,8 @@ dependencies = [ "multiversx-sc-codec", "multiversx-sc-derive", "num-traits", + "serde", + "serde-json-core", "unwrap-infallible", ] @@ -3494,6 +3516,7 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "serde", ] [[package]] @@ -3896,9 +3919,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" [[package]] name = "portable-atomic-util" @@ -4386,9 +4409,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -4579,9 +4602,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags 2.10.0", "errno", @@ -4644,9 +4667,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" [[package]] name = "salsa20" @@ -4818,6 +4841,36 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-features" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "multiversx-sc-scenario", + "num-bigint", + "serde", + "serde-json-core", +] + +[[package]] +name = "serde-features-meta" +version = "0.0.0" +dependencies = [ + "multiversx-sc-meta-lib", + "serde-features", +] + +[[package]] +name = "serde-json-core" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b81787e655bd59cecadc91f7b6b8651330b2be6c33246039a65e5cd6f4e0828" +dependencies = [ + "heapless", + "ryu", + "serde", +] + [[package]] name = "serde-wasm-bindgen" version = "0.6.5" @@ -4851,9 +4904,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" dependencies = [ "indexmap", "itoa", @@ -5868,7 +5921,7 @@ dependencies = [ "bytes", "cfg-if", "cmake", - "derive_more 2.1.0", + "derive_more 2.1.1", "indexmap", "js-sys", "more-asserts", @@ -6569,9 +6622,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f936044d677be1a1168fae1d03b583a285a5dd9d8cbf7b24c23aa1fc775235" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zopfli" diff --git a/Cargo.toml b/Cargo.toml index 00e883d4ea..4e3856be0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -191,6 +191,8 @@ members = [ "contracts/feature-tests/rust-testing-framework-tester/meta", "contracts/feature-tests/scenario-tester", "contracts/feature-tests/scenario-tester/meta", + "contracts/feature-tests/serde-features", + "contracts/feature-tests/serde-features/meta", "contracts/feature-tests/std-contract", "contracts/feature-tests/std-contract/meta", "contracts/feature-tests/use-module", diff --git a/contracts/feature-tests/serde-features/.gitignore b/contracts/feature-tests/serde-features/.gitignore new file mode 100644 index 0000000000..9494cb146e --- /dev/null +++ b/contracts/feature-tests/serde-features/.gitignore @@ -0,0 +1,7 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +*/target/ + +# The mxpy output +output diff --git a/contracts/feature-tests/serde-features/Cargo.toml b/contracts/feature-tests/serde-features/Cargo.toml new file mode 100644 index 0000000000..0c9d777f4c --- /dev/null +++ b/contracts/feature-tests/serde-features/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "serde-features" +version = "0.0.0" +authors = [ "you",] +edition = "2024" +publish = false + +[lib] +path = "src/serde_features.rs" + +[dependencies] +num-bigint = {version = "0.4.6", default-features = false, features = ["serde"] } +serde = { version = "1.0", optional = false, default-features = false, features = ["derive"] } +serde-json-core = { version = "0.6.0", optional = false, default-features = true} +# serde_json = { version = "1.0", optional = false, default-features = false, features = ["alloc", "raw_value"] } + +[dependencies.multiversx-sc] +version = "0.64.0" +path = "../../../framework/base" +features = ["alloc", "serde-util", "serde"] + +[dev-dependencies.multiversx-sc-scenario] +version = "0.64.0" +features = ["wasmer-experimental"] +path = "../../../framework/scenario" diff --git a/contracts/feature-tests/serde-features/meta/Cargo.toml b/contracts/feature-tests/serde-features/meta/Cargo.toml new file mode 100644 index 0000000000..c9ea30adec --- /dev/null +++ b/contracts/feature-tests/serde-features/meta/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "serde-features-meta" +version = "0.0.0" +edition = "2024" +publish = false +authors = ["you"] + +[dev-dependencies] + +[dependencies.serde-features] +path = ".." + +[dependencies.multiversx-sc-meta-lib] +version = "0.64.0" +path = "../../../../framework/meta-lib" +default-features = false diff --git a/contracts/feature-tests/serde-features/meta/src/main.rs b/contracts/feature-tests/serde-features/meta/src/main.rs new file mode 100644 index 0000000000..f1c6d2a12b --- /dev/null +++ b/contracts/feature-tests/serde-features/meta/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + multiversx_sc_meta_lib::cli_main::(); +} diff --git a/contracts/feature-tests/serde-features/multiversx.json b/contracts/feature-tests/serde-features/multiversx.json new file mode 100644 index 0000000000..7365539625 --- /dev/null +++ b/contracts/feature-tests/serde-features/multiversx.json @@ -0,0 +1,3 @@ +{ + "language": "rust" +} \ No newline at end of file diff --git a/contracts/feature-tests/serde-features/sc-config.toml b/contracts/feature-tests/serde-features/sc-config.toml new file mode 100644 index 0000000000..566a2460bc --- /dev/null +++ b/contracts/feature-tests/serde-features/sc-config.toml @@ -0,0 +1,2 @@ +[contracts.serde-features] +allocator = "static64k" diff --git a/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json b/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json new file mode 100644 index 0000000000..aa52865972 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json @@ -0,0 +1,64 @@ +{ + "steps": [ + { + "step": "setState", + "accounts": { + "sc:serde-features": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/serde-features.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "out_value_1", + "tx": { + "from": "address:an_account", + "to": "sc:serde-features", + "function": "out_value_1", + "arguments": [], + "gasLimit": "10,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "file:value_1.json" + ], + "status": "0", + "message": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "inc_serde_1", + "tx": { + "from": "address:an_account", + "to": "sc:serde-features", + "function": "inc_serde_1", + "arguments": [ + "file:value_1.json" + ], + "gasLimit": "105,500,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "file:value_1_inc.json" + ], + "status": "0", + "message": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} diff --git a/contracts/feature-tests/serde-features/scenarios/serde_2.scen.json b/contracts/feature-tests/serde-features/scenarios/serde_2.scen.json new file mode 100644 index 0000000000..3567ee37b2 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/serde_2.scen.json @@ -0,0 +1,64 @@ +{ + "steps": [ + { + "step": "setState", + "accounts": { + "sc:serde-features": { + "nonce": "0", + "balance": "0", + "code": "mxsc:../output/serde-features.mxsc.json" + }, + "address:an_account": { + "nonce": "0", + "balance": "0" + } + } + }, + { + "step": "scCall", + "id": "out_value_2", + "tx": { + "from": "address:an_account", + "to": "sc:serde-features", + "function": "out_value_2", + "arguments": [], + "gasLimit": "10,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "file:value_2.json" + ], + "status": "0", + "message": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "step": "scCall", + "id": "inc_serde_2", + "tx": { + "from": "address:an_account", + "to": "sc:serde-features", + "function": "inc_serde_2", + "arguments": [ + "file:value_2.json" + ], + "gasLimit": "105,500,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "file:value_2_inc.json" + ], + "status": "0", + "message": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + } + ] +} diff --git a/contracts/feature-tests/serde-features/scenarios/value_1.json b/contracts/feature-tests/serde-features/scenarios/value_1.json new file mode 100644 index 0000000000..bd443a1b49 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/value_1.json @@ -0,0 +1 @@ +{"value1":10,"value2":20} \ No newline at end of file diff --git a/contracts/feature-tests/serde-features/scenarios/value_1_inc.json b/contracts/feature-tests/serde-features/scenarios/value_1_inc.json new file mode 100644 index 0000000000..3a7fed7fe4 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/value_1_inc.json @@ -0,0 +1 @@ +{"value1":11,"value2":21} \ No newline at end of file diff --git a/contracts/feature-tests/serde-features/scenarios/value_1_pretty.json b/contracts/feature-tests/serde-features/scenarios/value_1_pretty.json new file mode 100644 index 0000000000..d17a66908a --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/value_1_pretty.json @@ -0,0 +1,4 @@ +{ + "value1": 10, + "value2": 20 +} \ No newline at end of file diff --git a/contracts/feature-tests/serde-features/scenarios/value_2.json b/contracts/feature-tests/serde-features/scenarios/value_2.json new file mode 100644 index 0000000000..1ba81930f4 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/value_2.json @@ -0,0 +1 @@ +{"mb":"abc"} \ No newline at end of file diff --git a/contracts/feature-tests/serde-features/scenarios/value_2_inc.json b/contracts/feature-tests/serde-features/scenarios/value_2_inc.json new file mode 100644 index 0000000000..acbbe732c9 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/value_2_inc.json @@ -0,0 +1 @@ +{"mb":"abcdef"} \ No newline at end of file diff --git a/contracts/feature-tests/serde-features/src/serde_features.rs b/contracts/feature-tests/serde-features/src/serde_features.rs new file mode 100644 index 0000000000..0a5238e675 --- /dev/null +++ b/contracts/feature-tests/serde-features/src/serde_features.rs @@ -0,0 +1,70 @@ +#![no_std] + +use multiversx_sc::imports::*; +use serde::{Deserialize, Serialize}; + +const BUFFER_SIZE: usize = 200; + +// #[type_abi] +// #[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, ManagedVecItem)] +#[derive(Serialize, Deserialize)] +pub struct SerdeStruct1 { + pub value1: u32, + pub value2: u32, +} + +#[derive(Serialize, Deserialize)] +pub struct SerdeStruct2 { + // pub v: Vec, + pub big_int: num_bigint::BigInt, +} + +#[derive(Serialize, Deserialize)] +#[serde(bound = "M: ManagedTypeApi")] +pub struct ManagedSerdeStruct { + mb: ManagedBuffer, +} + +#[multiversx_sc::contract] +pub trait SerdeFeatures { + #[init] + fn init(&self) {} + + #[endpoint] + fn out_value_1(&self) -> ManagedBuffer { + let s = SerdeStruct1 { + value1: 10, + value2: 20, + }; + + multiversx_sc::serde_util::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + } + + #[endpoint] + fn out_value_2(&self) -> ManagedBuffer { + let s = ManagedSerdeStruct:: { mb: "abc".into() }; + + multiversx_sc::serde_util::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + } + + #[endpoint] + fn inc_serde_1(&self, json: ManagedBuffer) -> ManagedBuffer { + let mut buf = [0u8; BUFFER_SIZE]; + let slice = json.load_to_byte_array(&mut buf); + let (mut s, _) = serde_json_core::from_slice::(slice) + .unwrap_or_else(|_| sc_panic!("deserialization failed")); + s.value1 += 1; + s.value2 += 1; + multiversx_sc::serde_util::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + } + + #[endpoint] + fn inc_serde_2(&self, json: ManagedBuffer) -> ManagedBuffer { + let mut buf = [0u8; BUFFER_SIZE]; + let slice = json.load_to_byte_array(&mut buf); + let (mut s, _) = serde_json_core::from_slice::>(slice) + .unwrap_or_else(|_| sc_panic!("deserialization failed")); + s.mb.append_bytes(b"def"); + multiversx_sc::serde_util::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + } +} diff --git a/contracts/feature-tests/serde-features/ssf.rs b/contracts/feature-tests/serde-features/ssf.rs new file mode 100644 index 0000000000..9c051b4669 --- /dev/null +++ b/contracts/feature-tests/serde-features/ssf.rs @@ -0,0 +1,1185 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use core::prelude::rust_2021::*; +#[macro_use] +extern crate core; +use core::num; +use multiversx_sc::imports::*; +use serde::{Deserialize, Serialize}; +const BUFFER_SIZE: usize = 200; +pub struct SerdeStruct1 { + pub value1: u32, + pub value2: u32, +} +#[doc(hidden)] +#[allow( + non_upper_case_globals, + unused_attributes, + unused_qualifications, + clippy::absolute_paths, +)] +const _: () = { + #[allow(unused_extern_crates, clippy::useless_attribute)] + extern crate serde as _serde; + #[automatically_derived] + impl _serde::Serialize for SerdeStruct1 { + fn serialize<__S>( + &self, + __serializer: __S, + ) -> _serde::__private::Result<__S::Ok, __S::Error> + where + __S: _serde::Serializer, + { + let mut __serde_state = _serde::Serializer::serialize_struct( + __serializer, + "SerdeStruct1", + false as usize + 1 + 1, + )?; + _serde::ser::SerializeStruct::serialize_field( + &mut __serde_state, + "value1", + &self.value1, + )?; + _serde::ser::SerializeStruct::serialize_field( + &mut __serde_state, + "value2", + &self.value2, + )?; + _serde::ser::SerializeStruct::end(__serde_state) + } + } +}; +#[doc(hidden)] +#[allow( + non_upper_case_globals, + unused_attributes, + unused_qualifications, + clippy::absolute_paths, +)] +const _: () = { + #[allow(unused_extern_crates, clippy::useless_attribute)] + extern crate serde as _serde; + #[automatically_derived] + impl<'de> _serde::Deserialize<'de> for SerdeStruct1 { + fn deserialize<__D>( + __deserializer: __D, + ) -> _serde::__private::Result + where + __D: _serde::Deserializer<'de>, + { + #[allow(non_camel_case_types)] + #[doc(hidden)] + enum __Field { + __field0, + __field1, + __ignore, + } + #[doc(hidden)] + struct __FieldVisitor; + #[automatically_derived] + impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { + type Value = __Field; + fn expecting( + &self, + __formatter: &mut _serde::__private::Formatter, + ) -> _serde::__private::fmt::Result { + _serde::__private::Formatter::write_str( + __formatter, + "field identifier", + ) + } + fn visit_u64<__E>( + self, + __value: u64, + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + 0u64 => _serde::__private::Ok(__Field::__field0), + 1u64 => _serde::__private::Ok(__Field::__field1), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + fn visit_str<__E>( + self, + __value: &str, + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + "value1" => _serde::__private::Ok(__Field::__field0), + "value2" => _serde::__private::Ok(__Field::__field1), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + fn visit_bytes<__E>( + self, + __value: &[u8], + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + b"value1" => _serde::__private::Ok(__Field::__field0), + b"value2" => _serde::__private::Ok(__Field::__field1), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + } + #[automatically_derived] + impl<'de> _serde::Deserialize<'de> for __Field { + #[inline] + fn deserialize<__D>( + __deserializer: __D, + ) -> _serde::__private::Result + where + __D: _serde::Deserializer<'de>, + { + _serde::Deserializer::deserialize_identifier( + __deserializer, + __FieldVisitor, + ) + } + } + #[doc(hidden)] + struct __Visitor<'de> { + marker: _serde::__private::PhantomData, + lifetime: _serde::__private::PhantomData<&'de ()>, + } + #[automatically_derived] + impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { + type Value = SerdeStruct1; + fn expecting( + &self, + __formatter: &mut _serde::__private::Formatter, + ) -> _serde::__private::fmt::Result { + _serde::__private::Formatter::write_str( + __formatter, + "struct SerdeStruct1", + ) + } + #[inline] + fn visit_seq<__A>( + self, + mut __seq: __A, + ) -> _serde::__private::Result + where + __A: _serde::de::SeqAccess<'de>, + { + let __field0 = match _serde::de::SeqAccess::next_element::< + u32, + >(&mut __seq)? { + _serde::__private::Some(__value) => __value, + _serde::__private::None => { + return _serde::__private::Err( + _serde::de::Error::invalid_length( + 0usize, + &"struct SerdeStruct1 with 2 elements", + ), + ); + } + }; + let __field1 = match _serde::de::SeqAccess::next_element::< + u32, + >(&mut __seq)? { + _serde::__private::Some(__value) => __value, + _serde::__private::None => { + return _serde::__private::Err( + _serde::de::Error::invalid_length( + 1usize, + &"struct SerdeStruct1 with 2 elements", + ), + ); + } + }; + _serde::__private::Ok(SerdeStruct1 { + value1: __field0, + value2: __field1, + }) + } + #[inline] + fn visit_map<__A>( + self, + mut __map: __A, + ) -> _serde::__private::Result + where + __A: _serde::de::MapAccess<'de>, + { + let mut __field0: _serde::__private::Option = _serde::__private::None; + let mut __field1: _serde::__private::Option = _serde::__private::None; + while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::< + __Field, + >(&mut __map)? { + match __key { + __Field::__field0 => { + if _serde::__private::Option::is_some(&__field0) { + return _serde::__private::Err( + <__A::Error as _serde::de::Error>::duplicate_field("value1"), + ); + } + __field0 = _serde::__private::Some( + _serde::de::MapAccess::next_value::(&mut __map)?, + ); + } + __Field::__field1 => { + if _serde::__private::Option::is_some(&__field1) { + return _serde::__private::Err( + <__A::Error as _serde::de::Error>::duplicate_field("value2"), + ); + } + __field1 = _serde::__private::Some( + _serde::de::MapAccess::next_value::(&mut __map)?, + ); + } + _ => { + let _ = _serde::de::MapAccess::next_value::< + _serde::de::IgnoredAny, + >(&mut __map)?; + } + } + } + let __field0 = match __field0 { + _serde::__private::Some(__field0) => __field0, + _serde::__private::None => { + _serde::__private::de::missing_field("value1")? + } + }; + let __field1 = match __field1 { + _serde::__private::Some(__field1) => __field1, + _serde::__private::None => { + _serde::__private::de::missing_field("value2")? + } + }; + _serde::__private::Ok(SerdeStruct1 { + value1: __field0, + value2: __field1, + }) + } + } + #[doc(hidden)] + const FIELDS: &'static [&'static str] = &["value1", "value2"]; + _serde::Deserializer::deserialize_struct( + __deserializer, + "SerdeStruct1", + FIELDS, + __Visitor { + marker: _serde::__private::PhantomData::, + lifetime: _serde::__private::PhantomData, + }, + ) + } + } +}; +pub struct SerdeStruct2 { + pub big_int: num_bigint::BigInt, +} +#[doc(hidden)] +#[allow( + non_upper_case_globals, + unused_attributes, + unused_qualifications, + clippy::absolute_paths, +)] +const _: () = { + #[allow(unused_extern_crates, clippy::useless_attribute)] + extern crate serde as _serde; + #[automatically_derived] + impl _serde::Serialize for SerdeStruct2 { + fn serialize<__S>( + &self, + __serializer: __S, + ) -> _serde::__private::Result<__S::Ok, __S::Error> + where + __S: _serde::Serializer, + { + let mut __serde_state = _serde::Serializer::serialize_struct( + __serializer, + "SerdeStruct2", + false as usize + 1, + )?; + _serde::ser::SerializeStruct::serialize_field( + &mut __serde_state, + "big_int", + &self.big_int, + )?; + _serde::ser::SerializeStruct::end(__serde_state) + } + } +}; +#[doc(hidden)] +#[allow( + non_upper_case_globals, + unused_attributes, + unused_qualifications, + clippy::absolute_paths, +)] +const _: () = { + #[allow(unused_extern_crates, clippy::useless_attribute)] + extern crate serde as _serde; + #[automatically_derived] + impl<'de> _serde::Deserialize<'de> for SerdeStruct2 { + fn deserialize<__D>( + __deserializer: __D, + ) -> _serde::__private::Result + where + __D: _serde::Deserializer<'de>, + { + #[allow(non_camel_case_types)] + #[doc(hidden)] + enum __Field { + __field0, + __ignore, + } + #[doc(hidden)] + struct __FieldVisitor; + #[automatically_derived] + impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { + type Value = __Field; + fn expecting( + &self, + __formatter: &mut _serde::__private::Formatter, + ) -> _serde::__private::fmt::Result { + _serde::__private::Formatter::write_str( + __formatter, + "field identifier", + ) + } + fn visit_u64<__E>( + self, + __value: u64, + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + 0u64 => _serde::__private::Ok(__Field::__field0), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + fn visit_str<__E>( + self, + __value: &str, + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + "big_int" => _serde::__private::Ok(__Field::__field0), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + fn visit_bytes<__E>( + self, + __value: &[u8], + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + b"big_int" => _serde::__private::Ok(__Field::__field0), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + } + #[automatically_derived] + impl<'de> _serde::Deserialize<'de> for __Field { + #[inline] + fn deserialize<__D>( + __deserializer: __D, + ) -> _serde::__private::Result + where + __D: _serde::Deserializer<'de>, + { + _serde::Deserializer::deserialize_identifier( + __deserializer, + __FieldVisitor, + ) + } + } + #[doc(hidden)] + struct __Visitor<'de> { + marker: _serde::__private::PhantomData, + lifetime: _serde::__private::PhantomData<&'de ()>, + } + #[automatically_derived] + impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> { + type Value = SerdeStruct2; + fn expecting( + &self, + __formatter: &mut _serde::__private::Formatter, + ) -> _serde::__private::fmt::Result { + _serde::__private::Formatter::write_str( + __formatter, + "struct SerdeStruct2", + ) + } + #[inline] + fn visit_seq<__A>( + self, + mut __seq: __A, + ) -> _serde::__private::Result + where + __A: _serde::de::SeqAccess<'de>, + { + let __field0 = match _serde::de::SeqAccess::next_element::< + num_bigint::BigInt, + >(&mut __seq)? { + _serde::__private::Some(__value) => __value, + _serde::__private::None => { + return _serde::__private::Err( + _serde::de::Error::invalid_length( + 0usize, + &"struct SerdeStruct2 with 1 element", + ), + ); + } + }; + _serde::__private::Ok(SerdeStruct2 { big_int: __field0 }) + } + #[inline] + fn visit_map<__A>( + self, + mut __map: __A, + ) -> _serde::__private::Result + where + __A: _serde::de::MapAccess<'de>, + { + let mut __field0: _serde::__private::Option = _serde::__private::None; + while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::< + __Field, + >(&mut __map)? { + match __key { + __Field::__field0 => { + if _serde::__private::Option::is_some(&__field0) { + return _serde::__private::Err( + <__A::Error as _serde::de::Error>::duplicate_field( + "big_int", + ), + ); + } + __field0 = _serde::__private::Some( + _serde::de::MapAccess::next_value::< + num_bigint::BigInt, + >(&mut __map)?, + ); + } + _ => { + let _ = _serde::de::MapAccess::next_value::< + _serde::de::IgnoredAny, + >(&mut __map)?; + } + } + } + let __field0 = match __field0 { + _serde::__private::Some(__field0) => __field0, + _serde::__private::None => { + _serde::__private::de::missing_field("big_int")? + } + }; + _serde::__private::Ok(SerdeStruct2 { big_int: __field0 }) + } + } + #[doc(hidden)] + const FIELDS: &'static [&'static str] = &["big_int"]; + _serde::Deserializer::deserialize_struct( + __deserializer, + "SerdeStruct2", + FIELDS, + __Visitor { + marker: _serde::__private::PhantomData::, + lifetime: _serde::__private::PhantomData, + }, + ) + } + } +}; +pub struct ManagedSerdeStruct { + mb: ManagedBuffer, +} +#[doc(hidden)] +#[allow( + non_upper_case_globals, + unused_attributes, + unused_qualifications, + clippy::absolute_paths, +)] +const _: () = { + #[allow(unused_extern_crates, clippy::useless_attribute)] + extern crate serde as _serde; + #[automatically_derived] + impl _serde::Serialize for ManagedSerdeStruct + where + M: _serde::Serialize, + { + fn serialize<__S>( + &self, + __serializer: __S, + ) -> _serde::__private::Result<__S::Ok, __S::Error> + where + __S: _serde::Serializer, + { + let mut __serde_state = _serde::Serializer::serialize_struct( + __serializer, + "ManagedSerdeStruct", + false as usize + 1, + )?; + _serde::ser::SerializeStruct::serialize_field( + &mut __serde_state, + "mb", + &self.mb, + )?; + _serde::ser::SerializeStruct::end(__serde_state) + } + } +}; +#[doc(hidden)] +#[allow( + non_upper_case_globals, + unused_attributes, + unused_qualifications, + clippy::absolute_paths, +)] +const _: () = { + #[allow(unused_extern_crates, clippy::useless_attribute)] + extern crate serde as _serde; + #[automatically_derived] + impl<'de, M: ManagedTypeApi> _serde::Deserialize<'de> for ManagedSerdeStruct + where + M: _serde::Deserialize<'de>, + { + fn deserialize<__D>( + __deserializer: __D, + ) -> _serde::__private::Result + where + __D: _serde::Deserializer<'de>, + { + #[allow(non_camel_case_types)] + #[doc(hidden)] + enum __Field { + __field0, + __ignore, + } + #[doc(hidden)] + struct __FieldVisitor; + #[automatically_derived] + impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { + type Value = __Field; + fn expecting( + &self, + __formatter: &mut _serde::__private::Formatter, + ) -> _serde::__private::fmt::Result { + _serde::__private::Formatter::write_str( + __formatter, + "field identifier", + ) + } + fn visit_u64<__E>( + self, + __value: u64, + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + 0u64 => _serde::__private::Ok(__Field::__field0), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + fn visit_str<__E>( + self, + __value: &str, + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + "mb" => _serde::__private::Ok(__Field::__field0), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + fn visit_bytes<__E>( + self, + __value: &[u8], + ) -> _serde::__private::Result + where + __E: _serde::de::Error, + { + match __value { + b"mb" => _serde::__private::Ok(__Field::__field0), + _ => _serde::__private::Ok(__Field::__ignore), + } + } + } + #[automatically_derived] + impl<'de> _serde::Deserialize<'de> for __Field { + #[inline] + fn deserialize<__D>( + __deserializer: __D, + ) -> _serde::__private::Result + where + __D: _serde::Deserializer<'de>, + { + _serde::Deserializer::deserialize_identifier( + __deserializer, + __FieldVisitor, + ) + } + } + #[doc(hidden)] + struct __Visitor<'de, M: ManagedTypeApi> + where + M: _serde::Deserialize<'de>, + { + marker: _serde::__private::PhantomData>, + lifetime: _serde::__private::PhantomData<&'de ()>, + } + #[automatically_derived] + impl<'de, M: ManagedTypeApi> _serde::de::Visitor<'de> for __Visitor<'de, M> + where + M: _serde::Deserialize<'de>, + { + type Value = ManagedSerdeStruct; + fn expecting( + &self, + __formatter: &mut _serde::__private::Formatter, + ) -> _serde::__private::fmt::Result { + _serde::__private::Formatter::write_str( + __formatter, + "struct ManagedSerdeStruct", + ) + } + #[inline] + fn visit_seq<__A>( + self, + mut __seq: __A, + ) -> _serde::__private::Result + where + __A: _serde::de::SeqAccess<'de>, + { + let __field0 = match _serde::de::SeqAccess::next_element::< + ManagedBuffer, + >(&mut __seq)? { + _serde::__private::Some(__value) => __value, + _serde::__private::None => { + return _serde::__private::Err( + _serde::de::Error::invalid_length( + 0usize, + &"struct ManagedSerdeStruct with 1 element", + ), + ); + } + }; + _serde::__private::Ok(ManagedSerdeStruct { mb: __field0 }) + } + #[inline] + fn visit_map<__A>( + self, + mut __map: __A, + ) -> _serde::__private::Result + where + __A: _serde::de::MapAccess<'de>, + { + let mut __field0: _serde::__private::Option> = _serde::__private::None; + while let _serde::__private::Some(__key) = _serde::de::MapAccess::next_key::< + __Field, + >(&mut __map)? { + match __key { + __Field::__field0 => { + if _serde::__private::Option::is_some(&__field0) { + return _serde::__private::Err( + <__A::Error as _serde::de::Error>::duplicate_field("mb"), + ); + } + __field0 = _serde::__private::Some( + _serde::de::MapAccess::next_value::< + ManagedBuffer, + >(&mut __map)?, + ); + } + _ => { + let _ = _serde::de::MapAccess::next_value::< + _serde::de::IgnoredAny, + >(&mut __map)?; + } + } + } + let __field0 = match __field0 { + _serde::__private::Some(__field0) => __field0, + _serde::__private::None => { + _serde::__private::de::missing_field("mb")? + } + }; + _serde::__private::Ok(ManagedSerdeStruct { mb: __field0 }) + } + } + #[doc(hidden)] + const FIELDS: &'static [&'static str] = &["mb"]; + _serde::Deserializer::deserialize_struct( + __deserializer, + "ManagedSerdeStruct", + FIELDS, + __Visitor { + marker: _serde::__private::PhantomData::>, + lifetime: _serde::__private::PhantomData, + }, + ) + } + } +}; +fn some_bigint() -> num_bigint::BigInt { + num_bigint::BigInt::from(12345678901234567890u128) +} +pub trait SerdeFeatures: multiversx_sc::contract_base::ContractBase + Sized { + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn init(&self) {} + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn out_value_1(&self) -> multiversx_sc::types::ManagedBuffer { + let s = SerdeStruct1 { + value1: 10, + value2: 20, + }; + multiversx_sc::serde::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + } + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn out_value_2(&self) -> multiversx_sc::types::ManagedBuffer { + let s = ManagedSerdeStruct:: { + mb: "abc".into(), + }; + multiversx_sc::serde::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + } + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn inc_serde_1( + &self, + json: multiversx_sc::types::ManagedBuffer, + ) -> multiversx_sc::types::ManagedBuffer { + let mut buf = [0u8; BUFFER_SIZE]; + let slice = json.load_to_byte_array(&mut buf); + let (mut s, _) = serde_json_core::from_slice::(slice) + .unwrap_or_else(|_| multiversx_sc::contract_base::ErrorHelper::< + Self::Api, + >::signal_error_with_message("deserialization failed")); + s.value1 += 1; + s.value2 += 1; + multiversx_sc::serde::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + } +} +pub trait AutoImpl: multiversx_sc::contract_base::ContractBase {} +impl SerdeFeatures for C +where + C: AutoImpl, +{} +impl AutoImpl for multiversx_sc::contract_base::UniversalContractObj +where + A: multiversx_sc::api::VMApi, +{} +pub trait EndpointWrappers: multiversx_sc::contract_base::ContractBase + SerdeFeatures { + #[inline] + fn call_init(&mut self) { + ::init_static(); + multiversx_sc::io::call_value_init::not_payable::(); + let () = multiversx_sc::io::load_endpoint_args::(()); + self.init(); + } + #[inline] + fn call_out_value_1(&mut self) { + ::init_static(); + multiversx_sc::io::call_value_init::not_payable::(); + let () = multiversx_sc::io::load_endpoint_args::(()); + let result = self.out_value_1(); + multiversx_sc::io::finish_multi::(&result); + } + #[inline] + fn call_out_value_2(&mut self) { + ::init_static(); + multiversx_sc::io::call_value_init::not_payable::(); + let () = multiversx_sc::io::load_endpoint_args::(()); + let result = self.out_value_2(); + multiversx_sc::io::finish_multi::(&result); + } + #[inline] + fn call_inc_serde_1(&mut self) { + ::init_static(); + multiversx_sc::io::call_value_init::not_payable::(); + let (json, ()) = multiversx_sc::io::load_endpoint_args::< + Self::Api, + (multiversx_sc::types::ManagedBuffer, ()), + >(("json", ())); + let result = self.inc_serde_1(json); + multiversx_sc::io::finish_multi::(&result); + } + fn call(&mut self, fn_name: &str) -> bool { + match fn_name { + "callBack" => { + self::EndpointWrappers::callback(self); + true + } + "init" if ::external_view_init_override() => { + multiversx_sc::external_view_contract::external_view_contract_constructor::< + Self::Api, + >(); + true + } + "init" if !::external_view_init_override() => { + self.call_init(); + true + } + "out_value_1" => { + self.call_out_value_1(); + true + } + "out_value_2" => { + self.call_out_value_2(); + true + } + "inc_serde_1" => { + self.call_inc_serde_1(); + true + } + other => false, + } + } + fn callback_selector( + &mut self, + ___cb_closure___: &multiversx_sc::types::CallbackClosureForDeser, + ) -> multiversx_sc::types::CallbackSelectorResult { + multiversx_sc::types::CallbackSelectorResult::NotProcessed + } + fn callback(&mut self) {} +} +impl EndpointWrappers for multiversx_sc::contract_base::UniversalContractObj +where + A: multiversx_sc::api::VMApi, +{} +pub struct AbiProvider {} +impl multiversx_sc::contract_base::ContractAbiProvider for AbiProvider { + type Api = multiversx_sc::api::uncallable::UncallableApi; + fn abi() -> multiversx_sc::abi::ContractAbi { + let mut contract_abi = multiversx_sc::abi::ContractAbi::new( + multiversx_sc::abi::BuildInfoAbi { + contract_crate: multiversx_sc::abi::ContractCrateBuildAbi { + name: "serde-features", + version: "0.0.0", + git_version: "", + }, + framework: multiversx_sc::abi::FrameworkBuildAbi::create(), + }, + &[], + "SerdeFeatures", + false, + ); + let mut endpoint_abi = multiversx_sc::abi::EndpointAbi::new( + "init", + "init", + multiversx_sc::abi::EndpointMutabilityAbi::Mutable, + multiversx_sc::abi::EndpointTypeAbi::Init, + ); + contract_abi.constructors.push(endpoint_abi); + let mut endpoint_abi = multiversx_sc::abi::EndpointAbi::new( + "out_value_1", + "out_value_1", + multiversx_sc::abi::EndpointMutabilityAbi::Mutable, + multiversx_sc::abi::EndpointTypeAbi::Endpoint, + ); + endpoint_abi.add_output::>(&[]); + contract_abi + .add_type_descriptions::>(); + contract_abi.endpoints.push(endpoint_abi); + let mut endpoint_abi = multiversx_sc::abi::EndpointAbi::new( + "out_value_2", + "out_value_2", + multiversx_sc::abi::EndpointMutabilityAbi::Mutable, + multiversx_sc::abi::EndpointTypeAbi::Endpoint, + ); + endpoint_abi.add_output::>(&[]); + contract_abi + .add_type_descriptions::>(); + contract_abi.endpoints.push(endpoint_abi); + let mut endpoint_abi = multiversx_sc::abi::EndpointAbi::new( + "inc_serde_1", + "inc_serde_1", + multiversx_sc::abi::EndpointMutabilityAbi::Mutable, + multiversx_sc::abi::EndpointTypeAbi::Endpoint, + ); + endpoint_abi.add_input::>("json"); + contract_abi + .add_type_descriptions::>(); + endpoint_abi.add_output::>(&[]); + contract_abi + .add_type_descriptions::>(); + contract_abi.endpoints.push(endpoint_abi); + contract_abi + } +} +pub struct ContractObj( + multiversx_sc::contract_base::UniversalContractObj, +) +where + A: multiversx_sc::api::VMApi; +impl multiversx_sc::contract_base::ContractBase for ContractObj +where + A: multiversx_sc::api::VMApi, +{ + type Api = A; +} +impl AutoImpl for ContractObj +where + A: multiversx_sc::api::VMApi, +{} +impl EndpointWrappers for ContractObj +where + A: multiversx_sc::api::VMApi, +{} +impl multiversx_sc::contract_base::CallableContract for ContractObj +where + A: multiversx_sc::api::VMApi + Send + Sync, +{ + fn call(&self, fn_name: &str) -> bool { + let mut obj = multiversx_sc::contract_base::UniversalContractObj::::new(); + EndpointWrappers::call(&mut obj, fn_name) + } +} +pub fn contract_obj() -> ContractObj +where + A: multiversx_sc::api::VMApi, +{ + ContractObj::(multiversx_sc::contract_base::UniversalContractObj::::new()) +} +pub struct ContractBuilder; +impl multiversx_sc::contract_base::CallableContractBuilder for self::ContractBuilder { + fn new_contract_obj( + &self, + ) -> multiversx_sc::types::heap::Box< + dyn multiversx_sc::contract_base::CallableContract, + > { + multiversx_sc::types::heap::Box::new(self::contract_obj::()) + } +} +#[allow(non_snake_case)] +pub mod __wasm__endpoints__ { + use super::EndpointWrappers; + pub fn init() + where + A: multiversx_sc::api::VMApi, + { + super::EndpointWrappers::call_init( + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), + ); + } + pub fn out_value_1() + where + A: multiversx_sc::api::VMApi, + { + super::EndpointWrappers::call_out_value_1( + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), + ); + } + pub fn out_value_2() + where + A: multiversx_sc::api::VMApi, + { + super::EndpointWrappers::call_out_value_2( + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), + ); + } + pub fn inc_serde_1() + where + A: multiversx_sc::api::VMApi, + { + super::EndpointWrappers::call_inc_serde_1( + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), + ); + } + pub fn callBack() + where + A: multiversx_sc::api::VMApi, + { + super::EndpointWrappers::callback( + &mut multiversx_sc::contract_base::UniversalContractObj::::new(), + ); + } +} +pub trait ProxyTrait: multiversx_sc::contract_base::ProxyObjBase + Sized { + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn init( + &mut self, + ) -> multiversx_sc::types::Tx< + multiversx_sc::types::TxScEnv, + (), + Self::To, + (), + (), + multiversx_sc::types::DeployCall, ()>, + multiversx_sc::types::OriginalResultMarker<()>, + > { + multiversx_sc::types::TxBaseWithEnv::new_tx_from_sc() + .raw_deploy() + .original_result() + .to(self.extract_proxy_to()) + } + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn out_value_1( + &mut self, + ) -> multiversx_sc::types::Tx< + multiversx_sc::types::TxScEnv, + (), + Self::To, + (), + (), + multiversx_sc::types::FunctionCall, + multiversx_sc::types::OriginalResultMarker< + multiversx_sc::types::ManagedBuffer, + >, + > { + multiversx_sc::types::TxBaseWithEnv::new_tx_from_sc() + .to(self.extract_proxy_to()) + .original_result() + .raw_call("out_value_1") + } + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn out_value_2( + &mut self, + ) -> multiversx_sc::types::Tx< + multiversx_sc::types::TxScEnv, + (), + Self::To, + (), + (), + multiversx_sc::types::FunctionCall, + multiversx_sc::types::OriginalResultMarker< + multiversx_sc::types::ManagedBuffer, + >, + > { + multiversx_sc::types::TxBaseWithEnv::new_tx_from_sc() + .to(self.extract_proxy_to()) + .original_result() + .raw_call("out_value_2") + } + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn inc_serde_1< + Arg0: multiversx_sc::types::ProxyArg< + multiversx_sc::types::ManagedBuffer, + >, + >( + &mut self, + json: Arg0, + ) -> multiversx_sc::types::Tx< + multiversx_sc::types::TxScEnv, + (), + Self::To, + (), + (), + multiversx_sc::types::FunctionCall, + multiversx_sc::types::OriginalResultMarker< + multiversx_sc::types::ManagedBuffer, + >, + > { + multiversx_sc::types::TxBaseWithEnv::new_tx_from_sc() + .to(self.extract_proxy_to()) + .original_result() + .raw_call("inc_serde_1") + .argument(&json) + } +} +pub struct Proxy +where + A: multiversx_sc::api::VMApi + 'static, +{ + _phantom: core::marker::PhantomData, +} +impl multiversx_sc::contract_base::ProxyObjBase for Proxy +where + A: multiversx_sc::api::VMApi + 'static, +{ + type Api = A; + type To = (); + fn extract_opt_address( + &mut self, + ) -> multiversx_sc::types::ManagedOption< + Self::Api, + multiversx_sc::types::ManagedAddress, + > { + multiversx_sc::types::ManagedOption::none() + } + fn extract_address(&mut self) -> multiversx_sc::types::ManagedAddress { + multiversx_sc::api::ErrorApiImpl::signal_error( + &::error_api_impl(), + multiversx_sc::err_msg::RECIPIENT_ADDRESS_NOT_SET.as_bytes(), + ) + } + fn extract_proxy_to(&mut self) -> Self::To {} +} +impl multiversx_sc::contract_base::ProxyObjNew for Proxy +where + A: multiversx_sc::api::VMApi + 'static, +{ + type ProxyTo = ProxyTo; + fn new_proxy_obj() -> Self { + Proxy { + _phantom: core::marker::PhantomData, + } + } + fn contract( + mut self, + address: multiversx_sc::types::ManagedAddress, + ) -> Self::ProxyTo { + ProxyTo { + address: multiversx_sc::types::ManagedOption::some(address), + } + } +} +pub struct ProxyTo +where + A: multiversx_sc::api::VMApi + 'static, +{ + pub address: multiversx_sc::types::ManagedOption< + A, + multiversx_sc::types::ManagedAddress, + >, +} +impl multiversx_sc::contract_base::ProxyObjBase for ProxyTo +where + A: multiversx_sc::api::VMApi + 'static, +{ + type Api = A; + type To = multiversx_sc::types::ManagedAddress; + fn extract_opt_address( + &mut self, + ) -> multiversx_sc::types::ManagedOption< + Self::Api, + multiversx_sc::types::ManagedAddress, + > { + core::mem::replace( + &mut self.address, + multiversx_sc::types::ManagedOption::none(), + ) + } + fn extract_address(&mut self) -> multiversx_sc::types::ManagedAddress { + let address = core::mem::replace( + &mut self.address, + multiversx_sc::types::ManagedOption::none(), + ); + address.unwrap_or_sc_panic(multiversx_sc::err_msg::RECIPIENT_ADDRESS_NOT_SET) + } + fn extract_proxy_to(&mut self) -> Self::To { + self.extract_address() + } +} +impl ProxyTrait for Proxy +where + A: multiversx_sc::api::VMApi, +{} +impl ProxyTrait for ProxyTo +where + A: multiversx_sc::api::VMApi, +{} diff --git a/contracts/feature-tests/serde-features/wasm/Cargo.lock b/contracts/feature-tests/serde-features/wasm/Cargo.lock new file mode 100644 index 0000000000..b34b822373 --- /dev/null +++ b/contracts/feature-tests/serde-features/wasm/Cargo.lock @@ -0,0 +1,315 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "endian-type" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "869b0adbda23651a9c5c0c3d270aac9fcb52e8622a8f2b17e57802d7791962f2" + +[[package]] +name = "generic-array" +version = "1.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf57c49a95fd1fe24b90b3033bee6dc7e8f1288d51494cb44e627c295e38542" +dependencies = [ + "rustversion", + "typenum", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "serde", + "stable_deref_trait", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" + +[[package]] +name = "multiversx-chain-core" +version = "0.21.0" +dependencies = [ + "bitflags", + "multiversx-sc-codec", +] + +[[package]] +name = "multiversx-sc" +version = "0.64.0" +dependencies = [ + "bitflags", + "generic-array", + "hex-literal", + "multiversx-chain-core", + "multiversx-sc-codec", + "multiversx-sc-derive", + "num-traits", + "serde", + "serde-json-core", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec" +version = "0.24.0" +dependencies = [ + "arrayvec", + "bitflags", + "multiversx-sc-codec-derive", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec-derive" +version = "0.24.0" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "multiversx-sc-derive" +version = "0.64.0" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "radix_trie", + "syn", +] + +[[package]] +name = "multiversx-sc-wasm-adapter" +version = "0.64.0" +dependencies = [ + "multiversx-sc", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radix_trie" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4431027dcd37fc2a73ef740b5f233aa805897935b8bce0195e41bbf9a3289a" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-features" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "num-bigint", + "serde", + "serde-json-core", +] + +[[package]] +name = "serde-features-wasm" +version = "0.0.0" +dependencies = [ + "multiversx-sc-wasm-adapter", + "serde-features", +] + +[[package]] +name = "serde-json-core" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b81787e655bd59cecadc91f7b6b8651330b2be6c33246039a65e5cd6f4e0828" +dependencies = [ + "heapless", + "ryu", + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unwrap-infallible" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e497bb1f828cc9fb236722c2eaa100dcf201563f38f4da6252357a59037adf31" diff --git a/contracts/feature-tests/serde-features/wasm/Cargo.toml b/contracts/feature-tests/serde-features/wasm/Cargo.toml new file mode 100644 index 0000000000..a77e342b93 --- /dev/null +++ b/contracts/feature-tests/serde-features/wasm/Cargo.toml @@ -0,0 +1,35 @@ +# Code generated by the multiversx-sc build system. DO NOT EDIT. + +# ########################################## +# ############## AUTO-GENERATED ############# +# ########################################## + +[package] +name = "serde-features-wasm" +version = "0.0.0" +edition = "2024" +publish = false + +[lib] +crate-type = ["cdylib"] + +[profile.release] +codegen-units = 1 +opt-level = "z" +lto = true +debug = false +panic = "abort" +overflow-checks = false + +[profile.dev] +panic = "abort" + +[dependencies.serde-features] +path = ".." + +[dependencies.multiversx-sc-wasm-adapter] +version = "0.64.0" +path = "../../../../framework/wasm-adapter" + +[workspace] +members = ["."] diff --git a/contracts/feature-tests/serde-features/wasm/src/lib.rs b/contracts/feature-tests/serde-features/wasm/src/lib.rs new file mode 100644 index 0000000000..67d5d66fe6 --- /dev/null +++ b/contracts/feature-tests/serde-features/wasm/src/lib.rs @@ -0,0 +1,28 @@ +// Code generated by the multiversx-sc build system. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +// Init: 1 +// Endpoints: 4 +// Async Callback (empty): 1 +// Total number of exported functions: 6 + +#![no_std] + +multiversx_sc_wasm_adapter::allocator!(static64k); +multiversx_sc_wasm_adapter::panic_handler!(); + +multiversx_sc_wasm_adapter::endpoints! { + serde_features + ( + init => init + out_value_1 => out_value_1 + out_value_2 => out_value_2 + inc_serde_1 => inc_serde_1 + inc_serde_2 => inc_serde_2 + ) +} + +multiversx_sc_wasm_adapter::async_callback_empty! {} diff --git a/framework/base/Cargo.toml b/framework/base/Cargo.toml index 072b33aee8..4d034cf4b2 100644 --- a/framework/base/Cargo.toml +++ b/framework/base/Cargo.toml @@ -23,6 +23,7 @@ alloc = [] std = ["multiversx-chain-core/std"] managed-buffer-builder-cached = [] esdt-token-payment-legacy-decode = [] +serde-util = ["serde", "serde-json-core"] contract-call-legacy = [] [dependencies] @@ -31,6 +32,9 @@ bitflags = "2.9" num-traits = { version = "=0.2.19", default-features = false } unwrap-infallible = "1.0" generic-array = "1.2.0" +serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] } +serde-json-core = { version = "0.6.0", optional = true, default-features = true} + [dependencies.multiversx-sc-derive] version = "=0.64.0" diff --git a/framework/base/src/lib.rs b/framework/base/src/lib.rs index 0dcde3ebea..48a0073243 100644 --- a/framework/base/src/lib.rs +++ b/framework/base/src/lib.rs @@ -32,6 +32,12 @@ pub mod storage; pub mod tuple_util; pub mod types; +#[cfg(feature = "serde-util")] +pub mod serde_util; + +#[cfg(feature = "serde")] +pub use serde; + #[cfg(feature = "std")] mod std_impl; diff --git a/framework/base/src/serde_util.rs b/framework/base/src/serde_util.rs new file mode 100644 index 0000000000..b8a0290805 --- /dev/null +++ b/framework/base/src/serde_util.rs @@ -0,0 +1,34 @@ +use crate::{ + api::{ManagedTypeApi, quick_signal_error}, + types::ManagedBuffer, +}; + +pub fn to_buffered_json(value: &T) -> ManagedBuffer +where + M: ManagedTypeApi, + T: serde::Serialize, +{ + let mut buf = [0u8; N]; + let used = serde_json_core::to_slice(value, &mut buf) + .unwrap_or_else(|_| quick_signal_error::("serialization failed")); + + ManagedBuffer::new_from_bytes(&buf[..used]) +} + +// pub fn with_deserialized_buffered_json<'a, M, T, F, R, const N: usize>( +// json: &'a ManagedBuffer, +// f: F, +// ) -> R +// where +// M: ManagedTypeApi, +// T: serde::Deserialize<'a>, +// R: 'static, +// F: FnOnce(&T) -> R, +// { +// let mut buf = [0u8; N]; +// let slice = json.load_to_byte_array(&mut buf); +// let (value, _) = serde_json_core::from_slice(slice) +// .unwrap_or_else(|_| quick_signal_error::("deserialization failed")); + +// f(&value) +// } diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index 55caf8a42a..86fc1e70de 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -591,3 +591,47 @@ impl core::fmt::Display for ManagedBuffer { s.fmt(f) } } + +#[cfg(feature = "serde")] +impl serde::Serialize for ManagedBuffer { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let bytes = self.to_boxed_bytes(); + let s = alloc::string::String::from_utf8(bytes.into_vec()) + .map_err(serde::ser::Error::custom)?; + serializer.serialize_str(&s) + } +} + +#[cfg(feature = "serde")] +impl<'de, M: ManagedTypeApi> serde::Deserialize<'de> for ManagedBuffer { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct ManagedBufferVisitor { + _phantom: core::marker::PhantomData, + } + + impl<'de, M: ManagedTypeApi> serde::de::Visitor<'de> for ManagedBufferVisitor { + type Value = ManagedBuffer; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("ManagedBuffer, as string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(ManagedBuffer::new_from_bytes(v.as_bytes())) + } + } + + deserializer.deserialize_str(ManagedBufferVisitor { + _phantom: core::marker::PhantomData, + }) + } +} diff --git a/framework/meta-lib/src/cargo_toml/cargo_toml_deps_raw.rs b/framework/meta-lib/src/cargo_toml/cargo_toml_deps_raw.rs index 40b02bf5b3..67d7e0ed9a 100644 --- a/framework/meta-lib/src/cargo_toml/cargo_toml_deps_raw.rs +++ b/framework/meta-lib/src/cargo_toml/cargo_toml_deps_raw.rs @@ -42,6 +42,13 @@ impl DependencyRawValue { if let Some(toml::Value::String(tag)) = table.get("tag") { result.tag = Some(tag.to_owned()); } + if let Some(toml::Value::Array(feature_values)) = table.get("features") { + for feature_value in feature_values { + if let toml::Value::String(feature) = feature_value { + result.features.insert(feature.to_owned()); + } + } + } result } _ => panic!("Unsupported dependency value"), diff --git a/framework/meta-lib/src/contract/meta_config.rs b/framework/meta-lib/src/contract/meta_config.rs index e27eb63d39..e4af4521f6 100644 --- a/framework/meta-lib/src/contract/meta_config.rs +++ b/framework/meta-lib/src/contract/meta_config.rs @@ -22,6 +22,8 @@ const SNIPPETS_RELATIVE_PATH: &str = "interactor"; const WASM_NO_MANAGED_EI: &str = "wasm-no-managed-ei"; const FRAMEWORK_NAME_BASE: &str = "multiversx-sc"; +const WASM_ADAPTER_FEATURE_WHITELIST: &[&str] = &[]; + #[derive(Debug)] pub struct MetaConfig { pub load_abi_git_version: bool, @@ -76,6 +78,13 @@ impl MetaConfig { let mut framework_dependency = main_cargo_toml_contents .dependency_raw_value(FRAMEWORK_NAME_BASE) .expect("missing framework dependency in Cargo.toml"); + + // filter original multiversx_sc feature flags (none at the moment) + framework_dependency + .features + .retain(|f| WASM_ADAPTER_FEATURE_WHITELIST.contains(&f.as_str())); + + // add std feature flag if contract.settings.std { framework_dependency.features.insert("std".to_owned()); }