From 22722b69d04936077a63e255ab49f7a3ce79cf29 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Mon, 25 Aug 2025 16:17:45 +0300 Subject: [PATCH 1/7] serde-features basic implementation --- Cargo.lock | 367 ++++++++++-------- Cargo.toml | 2 + .../feature-tests/serde-features/.gitignore | 7 + .../feature-tests/serde-features/Cargo.toml | 24 ++ .../serde-features/meta/Cargo.toml | 16 + .../serde-features/meta/src/main.rs | 3 + .../serde-features/multiversx.json | 3 + .../serde-features/sc-config.toml | 2 + .../scenarios/serde_1.scen.json | 86 ++++ .../serde-features/scenarios/value_1.json | 1 + .../scenarios/value_1_pretty.json | 4 + .../serde-features/scenarios/value_2.json | 1 + .../scenarios/value_2_pretty.json | 4 + .../serde-features/src/serde_features.rs | 46 +++ .../serde-features/wasm/Cargo.lock | 301 ++++++++++++++ .../serde-features/wasm/Cargo.toml | 35 ++ .../serde-features/wasm/src/lib.rs | 27 ++ 17 files changed, 772 insertions(+), 157 deletions(-) create mode 100644 contracts/feature-tests/serde-features/.gitignore create mode 100644 contracts/feature-tests/serde-features/Cargo.toml create mode 100644 contracts/feature-tests/serde-features/meta/Cargo.toml create mode 100644 contracts/feature-tests/serde-features/meta/src/main.rs create mode 100644 contracts/feature-tests/serde-features/multiversx.json create mode 100644 contracts/feature-tests/serde-features/sc-config.toml create mode 100644 contracts/feature-tests/serde-features/scenarios/serde_1.scen.json create mode 100644 contracts/feature-tests/serde-features/scenarios/value_1.json create mode 100644 contracts/feature-tests/serde-features/scenarios/value_1_pretty.json create mode 100644 contracts/feature-tests/serde-features/scenarios/value_2.json create mode 100644 contracts/feature-tests/serde-features/scenarios/value_2_pretty.json create mode 100644 contracts/feature-tests/serde-features/src/serde_features.rs create mode 100644 contracts/feature-tests/serde-features/wasm/Cargo.lock create mode 100644 contracts/feature-tests/serde-features/wasm/Cargo.toml create mode 100644 contracts/feature-tests/serde-features/wasm/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b3883478bd..7a96f45c56 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,7 +16,7 @@ dependencies = [ name = "abi-tester" version = "0.0.0" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "multiversx-sc", "multiversx-sc-meta-lib", "multiversx-sc-scenario", @@ -176,9 +176,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "anymap2" @@ -188,9 +188,9 @@ checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" [[package]] name = "arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" dependencies = [ "derive_arbitrary", ] @@ -330,18 +330,18 @@ version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "cexpr", "clang-sys", "itertools 0.13.0", "log", - "prettyplease 0.2.36", + "prettyplease 0.2.37", "proc-macro2", "quote", "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -381,9 +381,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" [[package]] name = "block-buffer" @@ -491,7 +491,7 @@ checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -508,9 +508,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.32" +version = "1.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" dependencies = [ "shlex", ] @@ -526,9 +526,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "cfg_aliases" @@ -608,9 +608,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.43" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50fd97c9dc2399518aa331917ac6f274280ec5eb34e555dd291899745c48ec6f" +checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" dependencies = [ "clap_builder", "clap_derive", @@ -618,9 +618,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.43" +version = "4.5.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35b5830294e1fa0462034af85cc95225a4cb07092c088c55bda3147cfcd8f65" +checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" dependencies = [ "anstream", "anstyle", @@ -630,14 +630,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.41" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -939,14 +939,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "darling" -version = "0.20.11" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +checksum = "08440b3dd222c3d0433e63e097463969485f112baff337dfdaca043a0d760570" dependencies = [ "darling_core", "darling_macro", @@ -954,26 +954,26 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.11" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +checksum = "d25b7912bc28a04ab1b7715a68ea03aaa15662b43a1a4b2c480531fd19f8bf7e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "darling_macro" -version = "0.20.11" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +checksum = "ce154b9bea7fb0c8e8326e62d00354000c36e79770ff21b8c84e3aa267d9d531" dependencies = [ "darling_core", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1013,13 +1013,13 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1030,7 +1030,7 @@ checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1050,7 +1050,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "unicode-xid", ] @@ -1089,7 +1089,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1098,13 +1098,13 @@ version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7d4c414c94bc830797115b8e5f434d58e7e80cb42ba88508c14bc6ea270625" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "byteorder", "lazy_static", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1116,7 +1116,7 @@ dependencies = [ "byteorder", "dynasm", "fnv", - "memmap2 0.9.7", + "memmap2 0.9.8", ] [[package]] @@ -1203,23 +1203,23 @@ dependencies = [ [[package]] name = "enumset" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ee17054f550fd7400e1906e2f9356c7672643ed34008a9e8abe147ccd2d821" +checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d07902c93376f1e96c34abc4d507c0911df3816cef50b01f5a2ff3ad8c370d" +checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1445,14 +1445,14 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1512,9 +1512,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -1686,7 +1686,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -1795,9 +1795,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "globset" @@ -2047,6 +2047,15 @@ dependencies = [ "tracing", ] +[[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.12.3" @@ -2072,6 +2081,17 @@ dependencies = [ "serde", ] +[[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" @@ -2173,19 +2193,21 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http 1.3.1", "http-body", "httparse", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -2389,7 +2411,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -2400,9 +2422,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -2492,7 +2514,7 @@ version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "cfg-if", "libc", ] @@ -2564,7 +2586,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -2685,9 +2707,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.174" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libloading" @@ -2705,7 +2727,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "libc", "redox_syscall", ] @@ -2860,7 +2882,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb4bdc8b0ce69932332cf76d24af69c3a155242af95c226b2ab6c2e371ed1149" dependencies = [ - "thiserror 2.0.12", + "thiserror 2.0.16", "zerocopy", "zerocopy-derive", ] @@ -2899,9 +2921,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" dependencies = [ "libc", ] @@ -3009,7 +3031,7 @@ name = "multiversx-chain-core" version = "0.17.0" dependencies = [ "bech32", - "bitflags 2.9.1", + "bitflags 2.9.3", "hex", "multiversx-sc-codec", "serde", @@ -3033,7 +3055,7 @@ name = "multiversx-chain-vm" version = "0.17.0" dependencies = [ "anyhow", - "bitflags 2.9.1", + "bitflags 2.9.3", "colored 3.0.0", "ed25519-dalek", "hex", @@ -3073,7 +3095,7 @@ dependencies = [ "loupe", "multiversx-chain-vm-executor", "rc-new-cyclic-fallible", - "thiserror 2.0.12", + "thiserror 2.0.16", "wasmer", "wasmer-types", ] @@ -3102,13 +3124,14 @@ dependencies = [ name = "multiversx-sc" version = "0.60.0" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "generic-array 1.2.0", "hex-literal", "multiversx-chain-core", "multiversx-sc-codec", "multiversx-sc-derive", "num-traits", + "serde", "unwrap-infallible", ] @@ -3117,7 +3140,7 @@ name = "multiversx-sc-codec" version = "0.23.1" dependencies = [ "arrayvec", - "bitflags 2.9.1", + "bitflags 2.9.3", "multiversx-sc-codec-derive", "num-bigint", "unwrap-infallible", @@ -3130,7 +3153,7 @@ dependencies = [ "hex", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3149,7 +3172,7 @@ dependencies = [ "proc-macro2", "quote", "radix_trie", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3350,7 +3373,7 @@ checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3528,7 +3551,7 @@ version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "cfg-if", "foreign-types", "libc", @@ -3545,7 +3568,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3720,9 +3743,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project" @@ -3741,7 +3764,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3862,12 +3885,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.36" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -3913,14 +3936,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -4029,7 +4052,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4063,7 +4086,7 @@ dependencies = [ "rustc-hash 2.1.1", "rustls", "socket2 0.5.10", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", "tracing", "web-time", @@ -4084,7 +4107,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.12", + "thiserror 2.0.16", "tinyvec", "tracing", "web-time", @@ -4215,9 +4238,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -4225,9 +4248,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -4262,7 +4285,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", ] [[package]] @@ -4317,9 +4340,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.22" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "base64", "bytes", @@ -4419,7 +4442,7 @@ checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4514,7 +4537,7 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "errno", "libc", "linux-raw-sys", @@ -4559,9 +4582,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ruzstd" @@ -4600,9 +4623,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22b2d775fb28f245817589471dd49c5edf64237f4a19d10ce9a92ff4651a27f4" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" dependencies = [ "sdd", ] @@ -4679,7 +4702,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "core-foundation", "core-foundation-sys", "libc", @@ -4750,6 +4773,36 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-features" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "multiversx-sc-scenario", + "serde", + "serde-json-core", + "serde_json", +] + +[[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.5.0" @@ -4780,14 +4833,14 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "indexmap 2.10.0", "itoa", @@ -4804,7 +4857,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -4850,7 +4903,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5072,9 +5125,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.104" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -5098,7 +5151,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5107,7 +5160,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "core-foundation", "system-configuration-sys", ] @@ -5152,15 +5205,15 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -5183,11 +5236,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.16", ] [[package]] @@ -5198,18 +5251,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5224,9 +5277,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -5281,7 +5334,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5416,7 +5469,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "bytes", "futures-util", "http 1.3.1", @@ -5459,7 +5512,7 @@ checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -5574,9 +5627,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.4" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "137a3c834eaf7139b73688502f3f1141a0337c5d8e4d9b536f9b8c796e26a7c4" dependencies = [ "form_urlencoded", "idna", @@ -5621,9 +5674,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -5731,7 +5784,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "wasm-bindgen-shared", ] @@ -5766,7 +5819,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5782,12 +5835,12 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.236.0" +version = "0.237.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3108979166ab0d3c7262d2e16a2190ffe784b2a5beb963edef154b5e8e07680b" +checksum = "efe92d1321afa53ffc88a57c497bb7330c3cf84c98ffdba4a4caf6a0684fad3c" dependencies = [ "leb128fmt", - "wasmparser 0.236.0", + "wasmparser 0.237.0", ] [[package]] @@ -5940,7 +5993,7 @@ version = "0.224.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04f17a5917c2ddd3819e84c661fae0d6ba29d7b9c1f0e96c708c65a9c4188e11" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", ] [[package]] @@ -5949,7 +6002,7 @@ version = "0.235.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "161296c618fa2d63f6ed5fffd1112937e803cb9ec71b32b01a76321555660917" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "hashbrown 0.15.5", "indexmap 2.10.0", "semver", @@ -5958,11 +6011,11 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.236.0" +version = "0.237.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d1eee846a705f6f3cb9d7b9f79b54583810f1fb57a1e3aea76d1742db2e3d2" +checksum = "7d2a40ca0d2bdf4b0bf36c13a737d0b2c58e4c8aaefe1c57f336dd75369ca250" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", "indexmap 2.10.0", "semver", ] @@ -5980,9 +6033,9 @@ dependencies = [ [[package]] name = "wast" -version = "236.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d6b6faeab519ba6fbf9b26add41617ca6f5553f99ebc33d876e591d2f4f3c6" +checksum = "fcf66f545acbd55082485cb9a6daab54579cb8628a027162253e8e9f5963c767" dependencies = [ "bumpalo", "leb128fmt", @@ -5993,9 +6046,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.236.0" +version = "1.237.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc31704322400f461f7f31a5f9190d5488aaeafb63ae69ad2b5888d2704dcb08" +checksum = "27975186f549e4b8d6878b627be732863883c72f7bf4dcf8f96e5f8242f73da9" dependencies = [ "wast", ] @@ -6040,11 +6093,11 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -6068,7 +6121,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -6079,7 +6132,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -6297,7 +6350,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.1", + "bitflags 2.9.3", ] [[package]] @@ -6426,7 +6479,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "synstructure", ] @@ -6447,7 +6500,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] @@ -6467,7 +6520,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", "synstructure", ] @@ -6496,14 +6549,14 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 2.0.106", ] [[package]] name = "zip" -version = "4.3.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aed4ac33e8eb078c89e6cbb1d5c4c7703ec6d299fc3e7c3695af8f8b423468b" +checksum = "8835eb39822904d39cb19465de1159e05d371973f0c6df3a365ad50565ddc8b9" dependencies = [ "arbitrary", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index 4c95cf2337..a43a1ffb38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,6 +189,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..906c12e2b1 --- /dev/null +++ b/contracts/feature-tests/serde-features/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "serde-features" +version = "0.0.0" +authors = [ "you",] +edition = "2021" +publish = false + +[lib] +path = "src/serde_features.rs" + +[dependencies] +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.60.0" +path = "../../../framework/base" +features = ["alloc", "serde"] + +[dev-dependencies.multiversx-sc-scenario] +version = "0.60.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..879cc7fbf0 --- /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 = "2021" +publish = false +authors = ["you"] + +[dev-dependencies] + +[dependencies.serde-features] +path = ".." + +[dependencies.multiversx-sc-meta-lib] +version = "0.60.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..1a04b24955 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json @@ -0,0 +1,86 @@ +{ + "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_pretty", + "tx": { + "from": "address:an_account", + "to": "sc:serde-features", + "function": "out_value_1_pretty", + "arguments": [], + "gasLimit": "10,000,000", + "gasPrice": "0" + }, + "expect": { + "out": [ + "file:value_1_pretty.json" + ], + "status": "0", + "message": "", + "logs": "*", + "gas": "*", + "refund": "*" + } + }, + { + "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_2.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_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..3a7fed7fe4 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/value_2.json @@ -0,0 +1 @@ +{"value1":11,"value2":21} \ No newline at end of file diff --git a/contracts/feature-tests/serde-features/scenarios/value_2_pretty.json b/contracts/feature-tests/serde-features/scenarios/value_2_pretty.json new file mode 100644 index 0000000000..d5b5753e83 --- /dev/null +++ b/contracts/feature-tests/serde-features/scenarios/value_2_pretty.json @@ -0,0 +1,4 @@ +{ + "value1": 11, + "value2": 21 +} \ 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..7c94232424 --- /dev/null +++ b/contracts/feature-tests/serde-features/src/serde_features.rs @@ -0,0 +1,46 @@ +#![no_std] + +use multiversx_sc::imports::*; +use serde::{Deserialize, Serialize}; + +// #[type_abi] +// #[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, ManagedVecItem)] +#[derive(Serialize, Deserialize)] +pub struct SerdeStruct { + pub value1: u32, + pub value2: u32, +} + +#[multiversx_sc::contract] +pub trait SerdeFeatures { + #[init] + fn init(&self) {} + + #[endpoint] + fn out_value_1(&self) -> Vec { + let s = SerdeStruct { + value1: 10, + value2: 20, + }; + // serde_json_core::to_slice(value, buf) + serde_json::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) + } + + #[endpoint] + fn out_value_1_pretty(&self) -> Vec { + let s = SerdeStruct { + value1: 10, + value2: 20, + }; + serde_json::to_vec_pretty(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) + } + + #[endpoint] + fn inc_serde_1(&self, input: &[u8]) -> Vec { + let (mut s, _) = serde_json_core::from_slice::(input) + .unwrap_or_else(|_| sc_panic!("deserialization failed")); + s.value1 += 1; + s.value2 += 1; + serde_json::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) + } +} 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..b7d93b099a --- /dev/null +++ b/contracts/feature-tests/serde-features/wasm/Cargo.lock @@ -0,0 +1,301 @@ +# 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.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[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.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "generic-array" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c8444bc9d71b935156cc0ccab7f622180808af7867b1daae6547d773591703" +dependencies = [ + "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.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcaaec4551594c969335c98c903c1397853d4198408ea609190f420500f6be71" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "multiversx-chain-core" +version = "0.17.0" +dependencies = [ + "bitflags", + "multiversx-sc-codec", +] + +[[package]] +name = "multiversx-sc" +version = "0.60.0" +dependencies = [ + "bitflags", + "generic-array", + "hex-literal", + "multiversx-chain-core", + "multiversx-sc-codec", + "multiversx-sc-derive", + "num-traits", + "serde", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec" +version = "0.23.1" +dependencies = [ + "arrayvec", + "bitflags", + "multiversx-sc-codec-derive", + "unwrap-infallible", +] + +[[package]] +name = "multiversx-sc-codec-derive" +version = "0.23.1" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "multiversx-sc-derive" +version = "0.60.0" +dependencies = [ + "hex", + "proc-macro2", + "quote", + "radix_trie", + "syn", +] + +[[package]] +name = "multiversx-sc-wasm-adapter" +version = "0.60.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-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.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-features" +version = "0.0.0" +dependencies = [ + "multiversx-sc", + "serde", + "serde-json-core", + "serde_json", +] + +[[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_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.143" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unwrap-infallible" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" 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..b2480574ae --- /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 = "2021" +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.60.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..ddd00139c9 --- /dev/null +++ b/contracts/feature-tests/serde-features/wasm/src/lib.rs @@ -0,0 +1,27 @@ +// Code generated by the multiversx-sc build system. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +// Init: 1 +// Endpoints: 3 +// Async Callback (empty): 1 +// Total number of exported functions: 5 + +#![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_1_pretty => out_value_1_pretty + inc_serde_1 => inc_serde_1 + ) +} + +multiversx_sc_wasm_adapter::async_callback_empty! {} From 769cddac28a7304fc46beab2bfb9ade863ccd1a8 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 26 Aug 2025 14:35:53 +0300 Subject: [PATCH 2/7] serde-json-core in serde-features --- Cargo.lock | 2 +- .../feature-tests/serde-features/Cargo.toml | 2 +- .../serde-features/sc-config.toml | 2 +- .../scenarios/serde_1.scen.json | 22 ------------ .../serde-features/src/serde_features.rs | 29 ++++++++-------- .../serde-features/wasm/Cargo.lock | 26 +------------- .../serde-features/wasm/src/lib.rs | 7 ++-- framework/base/Cargo.toml | 5 +++ framework/base/src/lib.rs | 3 ++ framework/base/src/serde.rs | 34 +++++++++++++++++++ 10 files changed, 64 insertions(+), 68 deletions(-) create mode 100644 framework/base/src/serde.rs diff --git a/Cargo.lock b/Cargo.lock index 7a96f45c56..7923e177cb 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -3132,6 +3132,7 @@ dependencies = [ "multiversx-sc-derive", "num-traits", "serde", + "serde-json-core", "unwrap-infallible", ] @@ -4781,7 +4782,6 @@ dependencies = [ "multiversx-sc-scenario", "serde", "serde-json-core", - "serde_json", ] [[package]] diff --git a/contracts/feature-tests/serde-features/Cargo.toml b/contracts/feature-tests/serde-features/Cargo.toml index 906c12e2b1..a9f3415859 100644 --- a/contracts/feature-tests/serde-features/Cargo.toml +++ b/contracts/feature-tests/serde-features/Cargo.toml @@ -11,7 +11,7 @@ path = "src/serde_features.rs" [dependencies] 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"] } +# serde_json = { version = "1.0", optional = false, default-features = false, features = ["alloc", "raw_value"] } [dependencies.multiversx-sc] version = "0.60.0" diff --git a/contracts/feature-tests/serde-features/sc-config.toml b/contracts/feature-tests/serde-features/sc-config.toml index 566a2460bc..70714ffa08 100644 --- a/contracts/feature-tests/serde-features/sc-config.toml +++ b/contracts/feature-tests/serde-features/sc-config.toml @@ -1,2 +1,2 @@ [contracts.serde-features] -allocator = "static64k" +# 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 index 1a04b24955..77b8869396 100644 --- a/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json +++ b/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json @@ -14,28 +14,6 @@ } } }, - { - "step": "scCall", - "id": "out_value_1_pretty", - "tx": { - "from": "address:an_account", - "to": "sc:serde-features", - "function": "out_value_1_pretty", - "arguments": [], - "gasLimit": "10,000,000", - "gasPrice": "0" - }, - "expect": { - "out": [ - "file:value_1_pretty.json" - ], - "status": "0", - "message": "", - "logs": "*", - "gas": "*", - "refund": "*" - } - }, { "step": "scCall", "id": "out_value_1", diff --git a/contracts/feature-tests/serde-features/src/serde_features.rs b/contracts/feature-tests/serde-features/src/serde_features.rs index 7c94232424..6ce72ec5cd 100644 --- a/contracts/feature-tests/serde-features/src/serde_features.rs +++ b/contracts/feature-tests/serde-features/src/serde_features.rs @@ -11,36 +11,37 @@ pub struct SerdeStruct { pub value2: u32, } +const BUFFER_SIZE: usize = 200; + #[multiversx_sc::contract] pub trait SerdeFeatures { #[init] fn init(&self) {} #[endpoint] - fn out_value_1(&self) -> Vec { + fn out_value_1(&self) -> ManagedBuffer { let s = SerdeStruct { value1: 10, value2: 20, }; - // serde_json_core::to_slice(value, buf) - serde_json::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) - } - #[endpoint] - fn out_value_1_pretty(&self) -> Vec { - let s = SerdeStruct { - value1: 10, - value2: 20, - }; - serde_json::to_vec_pretty(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) + multiversx_sc::serde::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + // serde_json_core::to_slice(value, buf) + // let v = serde_json_core::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")); + // v.to_vec() + // serde_json::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) } #[endpoint] - fn inc_serde_1(&self, input: &[u8]) -> Vec { - let (mut s, _) = serde_json_core::from_slice::(input) + fn inc_serde_1(&self, json: ManagedBuffer) -> ManagedBuffer { + // let (mut s, _) = serde_json_core::from_slice::(input) + // .unwrap_or_else(|_| sc_panic!("deserialization failed")); + 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; - serde_json::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) + multiversx_sc::serde::to_buffered_json::<_, _, BUFFER_SIZE>(&s) } } diff --git a/contracts/feature-tests/serde-features/wasm/Cargo.lock b/contracts/feature-tests/serde-features/wasm/Cargo.lock index b7d93b099a..43908147a8 100644 --- a/contracts/feature-tests/serde-features/wasm/Cargo.lock +++ b/contracts/feature-tests/serde-features/wasm/Cargo.lock @@ -73,18 +73,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcaaec4551594c969335c98c903c1397853d4198408ea609190f420500f6be71" -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - [[package]] name = "multiversx-chain-core" version = "0.17.0" @@ -105,6 +93,7 @@ dependencies = [ "multiversx-sc-derive", "num-traits", "serde", + "serde-json-core", "unwrap-infallible", ] @@ -214,7 +203,6 @@ dependencies = [ "multiversx-sc", "serde", "serde-json-core", - "serde_json", ] [[package]] @@ -247,18 +235,6 @@ dependencies = [ "syn", ] -[[package]] -name = "serde_json" -version = "1.0.143" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - [[package]] name = "smallvec" version = "1.15.1" diff --git a/contracts/feature-tests/serde-features/wasm/src/lib.rs b/contracts/feature-tests/serde-features/wasm/src/lib.rs index ddd00139c9..6afedd250c 100644 --- a/contracts/feature-tests/serde-features/wasm/src/lib.rs +++ b/contracts/feature-tests/serde-features/wasm/src/lib.rs @@ -5,13 +5,13 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 3 +// Endpoints: 2 // Async Callback (empty): 1 -// Total number of exported functions: 5 +// Total number of exported functions: 4 #![no_std] -multiversx_sc_wasm_adapter::allocator!(static64k); +multiversx_sc_wasm_adapter::allocator!(); multiversx_sc_wasm_adapter::panic_handler!(); multiversx_sc_wasm_adapter::endpoints! { @@ -19,7 +19,6 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init out_value_1 => out_value_1 - out_value_1_pretty => out_value_1_pretty inc_serde_1 => inc_serde_1 ) } diff --git a/framework/base/Cargo.toml b/framework/base/Cargo.toml index 35c702f37b..45181c7ba4 100644 --- a/framework/base/Cargo.toml +++ b/framework/base/Cargo.toml @@ -24,6 +24,8 @@ std = ["multiversx-chain-core/std"] managed-buffer-builder-cached = [] esdt-token-payment-legacy-decode = [] barnard = [] +default = ["serde-json-io"] +serde-json-io = ["serde", "serde-json-core"] [dependencies] hex-literal = "1.0" @@ -31,6 +33,9 @@ bitflags = "2.9" num-traits = { version = "=0.2.19", default-features = false } unwrap-infallible = "0.1.5" 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.60.0" diff --git a/framework/base/src/lib.rs b/framework/base/src/lib.rs index 0dcde3ebea..286b5b8ef2 100644 --- a/framework/base/src/lib.rs +++ b/framework/base/src/lib.rs @@ -32,6 +32,9 @@ pub mod storage; pub mod tuple_util; pub mod types; +#[cfg(feature = "serde")] +pub mod serde; + #[cfg(feature = "std")] mod std_impl; diff --git a/framework/base/src/serde.rs b/framework/base/src/serde.rs new file mode 100644 index 0000000000..22f5efaf17 --- /dev/null +++ b/framework/base/src/serde.rs @@ -0,0 +1,34 @@ +use crate::{ + api::{quick_signal_error, ManagedTypeApi}, + 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) +// } From f2d0754af144608e4cecf8b18c975f0d3ce8628c Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 26 Aug 2025 19:15:19 +0300 Subject: [PATCH 3/7] serde impl for ManagedBuffer with example --- Cargo.lock | 2 + .../feature-tests/serde-features/Cargo.toml | 3 +- .../serde-features/sc-config.toml | 2 +- .../scenarios/serde_1.scen.json | 2 +- .../scenarios/serde_2.scen.json | 64 + .../serde-features/scenarios/value_1_inc.json | 1 + .../serde-features/scenarios/value_2.json | 2 +- .../serde-features/scenarios/value_2_inc.json | 1 + .../scenarios/value_2_pretty.json | 4 - .../serde-features/src/serde_features.rs | 46 +- contracts/feature-tests/serde-features/ssf.rs | 1185 +++++++++++++++++ .../serde-features/wasm/Cargo.lock | 21 + .../serde-features/wasm/Cargo.toml | 1 + .../serde-features/wasm/src/lib.rs | 8 +- framework/base/Cargo.toml | 4 +- .../base/src/api/external_view/ev_wrapper.rs | 26 + .../src/api/uncallable/vm_api_uncallable.rs | 20 + framework/base/src/api/vm_api.rs | 38 + framework/base/src/lib.rs | 5 +- .../base/src/{serde.rs => serde_util.rs} | 0 .../src/types/managed/basic/managed_buffer.rs | 55 + .../src/cargo_toml/cargo_toml_deps_raw.rs | 7 + .../meta-lib/src/contract/meta_config.rs | 7 + framework/wasm-adapter/Cargo.toml | 1 + framework/wasm-adapter/src/api/vm_api_node.rs | 20 + 25 files changed, 1499 insertions(+), 26 deletions(-) create mode 100644 contracts/feature-tests/serde-features/scenarios/serde_2.scen.json create mode 100644 contracts/feature-tests/serde-features/scenarios/value_1_inc.json create mode 100644 contracts/feature-tests/serde-features/scenarios/value_2_inc.json delete mode 100644 contracts/feature-tests/serde-features/scenarios/value_2_pretty.json create mode 100644 contracts/feature-tests/serde-features/ssf.rs rename framework/base/src/{serde.rs => serde_util.rs} (100%) diff --git a/Cargo.lock b/Cargo.lock index 7923e177cb..2ceb08606f 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -3481,6 +3481,7 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "serde", ] [[package]] @@ -4780,6 +4781,7 @@ version = "0.0.0" dependencies = [ "multiversx-sc", "multiversx-sc-scenario", + "num-bigint", "serde", "serde-json-core", ] diff --git a/contracts/feature-tests/serde-features/Cargo.toml b/contracts/feature-tests/serde-features/Cargo.toml index a9f3415859..7bd33fa065 100644 --- a/contracts/feature-tests/serde-features/Cargo.toml +++ b/contracts/feature-tests/serde-features/Cargo.toml @@ -9,6 +9,7 @@ publish = false 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"] } @@ -16,7 +17,7 @@ serde-json-core = { version = "0.6.0", optional = false, default-features = true [dependencies.multiversx-sc] version = "0.60.0" path = "../../../framework/base" -features = ["alloc", "serde"] +features = ["alloc", "serde-util", "serde"] [dev-dependencies.multiversx-sc-scenario] version = "0.60.0" diff --git a/contracts/feature-tests/serde-features/sc-config.toml b/contracts/feature-tests/serde-features/sc-config.toml index 70714ffa08..566a2460bc 100644 --- a/contracts/feature-tests/serde-features/sc-config.toml +++ b/contracts/feature-tests/serde-features/sc-config.toml @@ -1,2 +1,2 @@ [contracts.serde-features] -# allocator = "static64k" +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 index 77b8869396..aa52865972 100644 --- a/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json +++ b/contracts/feature-tests/serde-features/scenarios/serde_1.scen.json @@ -51,7 +51,7 @@ }, "expect": { "out": [ - "file:value_2.json" + "file:value_1_inc.json" ], "status": "0", "message": "", 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_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_2.json b/contracts/feature-tests/serde-features/scenarios/value_2.json index 3a7fed7fe4..1ba81930f4 100644 --- a/contracts/feature-tests/serde-features/scenarios/value_2.json +++ b/contracts/feature-tests/serde-features/scenarios/value_2.json @@ -1 +1 @@ -{"value1":11,"value2":21} \ No newline at end of file +{"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/scenarios/value_2_pretty.json b/contracts/feature-tests/serde-features/scenarios/value_2_pretty.json deleted file mode 100644 index d5b5753e83..0000000000 --- a/contracts/feature-tests/serde-features/scenarios/value_2_pretty.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "value1": 11, - "value2": 21 -} \ 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 index 6ce72ec5cd..f44c25b3d4 100644 --- a/contracts/feature-tests/serde-features/src/serde_features.rs +++ b/contracts/feature-tests/serde-features/src/serde_features.rs @@ -3,15 +3,26 @@ 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 SerdeStruct { +pub struct SerdeStruct1 { pub value1: u32, pub value2: u32, } -const BUFFER_SIZE: usize = 200; +#[derive(Serialize, Deserialize)] +pub struct SerdeStruct2 { + // pub v: Vec, + pub big_int: num_bigint::BigInt, +} + +#[derive(Serialize, Deserialize)] +pub struct ManagedSerdeStruct { + mb: ManagedBuffer, +} #[multiversx_sc::contract] pub trait SerdeFeatures { @@ -20,28 +31,39 @@ pub trait SerdeFeatures { #[endpoint] fn out_value_1(&self) -> ManagedBuffer { - let s = SerdeStruct { + let s = SerdeStruct1 { value1: 10, value2: 20, }; - multiversx_sc::serde::to_buffered_json::<_, _, BUFFER_SIZE>(&s) - // serde_json_core::to_slice(value, buf) - // let v = serde_json_core::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")); - // v.to_vec() - // serde_json::to_vec(&s).unwrap_or_else(|_| sc_panic!("serialization failed")) + 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 s, _) = serde_json_core::from_slice::(input) - // .unwrap_or_else(|_| sc_panic!("deserialization failed")); let mut buf = [0u8; BUFFER_SIZE]; let slice = json.load_to_byte_array(&mut buf); - let (mut s, _) = serde_json_core::from_slice::(slice) + 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::to_buffered_json::<_, _, BUFFER_SIZE>(&s) + 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 index 43908147a8..dc167e0aa2 100644 --- a/contracts/feature-tests/serde-features/wasm/Cargo.lock +++ b/contracts/feature-tests/serde-features/wasm/Cargo.lock @@ -144,6 +144,26 @@ 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" @@ -201,6 +221,7 @@ name = "serde-features" version = "0.0.0" dependencies = [ "multiversx-sc", + "num-bigint", "serde", "serde-json-core", ] diff --git a/contracts/feature-tests/serde-features/wasm/Cargo.toml b/contracts/feature-tests/serde-features/wasm/Cargo.toml index b2480574ae..21c8ed6317 100644 --- a/contracts/feature-tests/serde-features/wasm/Cargo.toml +++ b/contracts/feature-tests/serde-features/wasm/Cargo.toml @@ -30,6 +30,7 @@ path = ".." [dependencies.multiversx-sc-wasm-adapter] version = "0.60.0" path = "../../../../framework/wasm-adapter" +features = ["serde"] [workspace] members = ["."] diff --git a/contracts/feature-tests/serde-features/wasm/src/lib.rs b/contracts/feature-tests/serde-features/wasm/src/lib.rs index 6afedd250c..67d5d66fe6 100644 --- a/contracts/feature-tests/serde-features/wasm/src/lib.rs +++ b/contracts/feature-tests/serde-features/wasm/src/lib.rs @@ -5,13 +5,13 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 2 +// Endpoints: 4 // Async Callback (empty): 1 -// Total number of exported functions: 4 +// Total number of exported functions: 6 #![no_std] -multiversx_sc_wasm_adapter::allocator!(); +multiversx_sc_wasm_adapter::allocator!(static64k); multiversx_sc_wasm_adapter::panic_handler!(); multiversx_sc_wasm_adapter::endpoints! { @@ -19,7 +19,9 @@ multiversx_sc_wasm_adapter::endpoints! { ( 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 ) } diff --git a/framework/base/Cargo.toml b/framework/base/Cargo.toml index 45181c7ba4..3e72a46e8c 100644 --- a/framework/base/Cargo.toml +++ b/framework/base/Cargo.toml @@ -24,8 +24,8 @@ std = ["multiversx-chain-core/std"] managed-buffer-builder-cached = [] esdt-token-payment-legacy-decode = [] barnard = [] -default = ["serde-json-io"] -serde-json-io = ["serde", "serde-json-core"] +# default = ["serde-json-io"] +serde-util = ["serde", "serde-json-core"] [dependencies] hex-literal = "1.0" diff --git a/framework/base/src/api/external_view/ev_wrapper.rs b/framework/base/src/api/external_view/ev_wrapper.rs index 6b88231e5b..fed2b590aa 100644 --- a/framework/base/src/api/external_view/ev_wrapper.rs +++ b/framework/base/src/api/external_view/ev_wrapper.rs @@ -189,3 +189,29 @@ where } impl Eq for ExternalViewApi where A: VMApi {} + +#[cfg(feature = "serde")] +impl serde::Serialize for ExternalViewApi +where + A: VMApi, +{ + fn serialize(&self, _serializer: S) -> Result + where + S: serde::Serializer, + { + unreachable!() + } +} + +#[cfg(feature = "serde")] +impl<'de, A> serde::de::Deserialize<'de> for ExternalViewApi +where + A: VMApi, +{ + fn deserialize(_deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + unreachable!() + } +} diff --git a/framework/base/src/api/uncallable/vm_api_uncallable.rs b/framework/base/src/api/uncallable/vm_api_uncallable.rs index 1b6a610099..6a489fb474 100644 --- a/framework/base/src/api/uncallable/vm_api_uncallable.rs +++ b/framework/base/src/api/uncallable/vm_api_uncallable.rs @@ -27,3 +27,23 @@ impl HandleTypeInfo for UncallableApi { type ManagedMapHandle = i32; } + +#[cfg(feature = "serde")] +impl serde::Serialize for UncallableApi { + fn serialize(&self, _serializer: S) -> Result + where + S: serde::Serializer, + { + unreachable!() + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::de::Deserialize<'de> for UncallableApi { + fn deserialize(_deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + unreachable!() + } +} diff --git a/framework/base/src/api/vm_api.rs b/framework/base/src/api/vm_api.rs index c7cac0daa2..03358e0ded 100644 --- a/framework/base/src/api/vm_api.rs +++ b/framework/base/src/api/vm_api.rs @@ -4,6 +4,7 @@ use super::{ StorageReadApiImpl, StorageWriteApi, }; +#[cfg(not(feature = "serde"))] pub trait VMApi: ManagedTypeApi + BlockchainApi @@ -37,3 +38,40 @@ pub trait VMApi: Self::storage_read_api_impl().storage_read_api_init(); } } + +#[cfg(feature = "serde")] +pub trait VMApi: + ManagedTypeApi + + BlockchainApi + + CallValueApi + + CryptoApi + + EndpointArgumentApi + + EndpointFinishApi + + ErrorApi + + LogApi + + SendApi + + StorageReadApi + + StorageWriteApi + + PrintApi + + CallTypeApi + + StorageMapperApi + + Clone // TODO: remove + + PartialEq // for helping derive PartialEq for managed types + + Eq + + Send + + Sync + + serde::ser::Serialize + + serde::de::DeserializeOwned +{ + /// Slightly hacky way of overriding the constructor for external view contracts. + /// + /// Only required for the tests, in production the meta crate makes sure to replace it. + /// + /// TODO: find a more robust and maybe extendable solution. + fn external_view_init_override() -> bool { + false + } + fn init_static() { + Self::storage_read_api_impl().storage_read_api_init(); + } +} diff --git a/framework/base/src/lib.rs b/framework/base/src/lib.rs index 286b5b8ef2..48a0073243 100644 --- a/framework/base/src/lib.rs +++ b/framework/base/src/lib.rs @@ -32,8 +32,11 @@ pub mod storage; pub mod tuple_util; pub mod types; +#[cfg(feature = "serde-util")] +pub mod serde_util; + #[cfg(feature = "serde")] -pub mod serde; +pub use serde; #[cfg(feature = "std")] mod std_impl; diff --git a/framework/base/src/serde.rs b/framework/base/src/serde_util.rs similarity index 100% rename from framework/base/src/serde.rs rename to framework/base/src/serde_util.rs diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index c3fd03f781..869d6b59f8 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -589,3 +589,58 @@ 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 = str::from_utf8(bytes.as_slice()).map_err(|err| serde::ser::Error::custom(err))?; + 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>, +// { +// deserializer.deserialize_str(visitor) +// let s = alloc::string::String::deserialize(deserializer)?; +// Ok(ManagedBuffer::new_from_bytes(s.as_bytes())) +// } +// } + +#[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 c152135d63..aba7ef9445 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] = &["serde"]; + #[derive(Debug)] pub struct MetaConfig { pub load_abi_git_version: bool, @@ -79,6 +81,11 @@ impl MetaConfig { if contract.settings.std { framework_dependency.features.insert("std".to_owned()); } + framework_dependency.features = framework_dependency + .features + .into_iter() + .filter(|f| WASM_ADAPTER_FEATURE_WHITELIST.contains(&f.as_str())) + .collect(); let cargo_toml_data = WasmCargoTomlData { name: contract.wasm_crate_name.clone(), diff --git a/framework/wasm-adapter/Cargo.toml b/framework/wasm-adapter/Cargo.toml index bd7e34cb14..98eb14fcc1 100644 --- a/framework/wasm-adapter/Cargo.toml +++ b/framework/wasm-adapter/Cargo.toml @@ -23,6 +23,7 @@ categories = [ [features] std = ["multiversx-sc/std"] +serde = ["multiversx-sc/serde"] [dependencies.multiversx-sc] version = "=0.60.0" diff --git a/framework/wasm-adapter/src/api/vm_api_node.rs b/framework/wasm-adapter/src/api/vm_api_node.rs index 56c29e44e2..f01f82a4df 100644 --- a/framework/wasm-adapter/src/api/vm_api_node.rs +++ b/framework/wasm-adapter/src/api/vm_api_node.rs @@ -38,3 +38,23 @@ impl HandleTypeInfo for VmApiImpl { type ManagedMapHandle = i32; } + +#[cfg(feature = "serde")] +impl multiversx_sc::serde::Serialize for VmApiImpl { + fn serialize(&self, _serializer: S) -> Result + where + S: multiversx_sc::serde::Serializer, + { + unreachable!() + } +} + +#[cfg(feature = "serde")] +impl<'de> multiversx_sc::serde::de::Deserialize<'de> for VmApiImpl { + fn deserialize(_deserializer: D) -> Result + where + D: multiversx_sc::serde::Deserializer<'de>, + { + unreachable!() + } +} \ No newline at end of file From 7d91394f66978a5651b3c53bb3aeb624f627cba0 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 26 Aug 2025 19:23:43 +0300 Subject: [PATCH 4/7] serde bounds fix + cleanup --- .../serde-features/src/serde_features.rs | 1 + .../serde-features/wasm/Cargo.toml | 1 - .../base/src/api/external_view/ev_wrapper.rs | 25 ------------ .../src/api/uncallable/vm_api_uncallable.rs | 19 ---------- framework/base/src/api/vm_api.rs | 38 ------------------- .../src/types/managed/basic/managed_buffer.rs | 12 ------ .../meta-lib/src/contract/meta_config.rs | 2 +- framework/wasm-adapter/Cargo.toml | 1 - framework/wasm-adapter/src/api/vm_api_node.rs | 20 ---------- 9 files changed, 2 insertions(+), 117 deletions(-) diff --git a/contracts/feature-tests/serde-features/src/serde_features.rs b/contracts/feature-tests/serde-features/src/serde_features.rs index f44c25b3d4..983520b2d8 100644 --- a/contracts/feature-tests/serde-features/src/serde_features.rs +++ b/contracts/feature-tests/serde-features/src/serde_features.rs @@ -20,6 +20,7 @@ pub struct SerdeStruct2 { } #[derive(Serialize, Deserialize)] +#[serde(bound = "M: ManagedTypeApi")] pub struct ManagedSerdeStruct { mb: ManagedBuffer, } diff --git a/contracts/feature-tests/serde-features/wasm/Cargo.toml b/contracts/feature-tests/serde-features/wasm/Cargo.toml index 21c8ed6317..b2480574ae 100644 --- a/contracts/feature-tests/serde-features/wasm/Cargo.toml +++ b/contracts/feature-tests/serde-features/wasm/Cargo.toml @@ -30,7 +30,6 @@ path = ".." [dependencies.multiversx-sc-wasm-adapter] version = "0.60.0" path = "../../../../framework/wasm-adapter" -features = ["serde"] [workspace] members = ["."] diff --git a/framework/base/src/api/external_view/ev_wrapper.rs b/framework/base/src/api/external_view/ev_wrapper.rs index fed2b590aa..8f012a233f 100644 --- a/framework/base/src/api/external_view/ev_wrapper.rs +++ b/framework/base/src/api/external_view/ev_wrapper.rs @@ -190,28 +190,3 @@ where impl Eq for ExternalViewApi where A: VMApi {} -#[cfg(feature = "serde")] -impl serde::Serialize for ExternalViewApi -where - A: VMApi, -{ - fn serialize(&self, _serializer: S) -> Result - where - S: serde::Serializer, - { - unreachable!() - } -} - -#[cfg(feature = "serde")] -impl<'de, A> serde::de::Deserialize<'de> for ExternalViewApi -where - A: VMApi, -{ - fn deserialize(_deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - unreachable!() - } -} diff --git a/framework/base/src/api/uncallable/vm_api_uncallable.rs b/framework/base/src/api/uncallable/vm_api_uncallable.rs index 6a489fb474..4dba88a17a 100644 --- a/framework/base/src/api/uncallable/vm_api_uncallable.rs +++ b/framework/base/src/api/uncallable/vm_api_uncallable.rs @@ -28,22 +28,3 @@ impl HandleTypeInfo for UncallableApi { type ManagedMapHandle = i32; } -#[cfg(feature = "serde")] -impl serde::Serialize for UncallableApi { - fn serialize(&self, _serializer: S) -> Result - where - S: serde::Serializer, - { - unreachable!() - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::de::Deserialize<'de> for UncallableApi { - fn deserialize(_deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - unreachable!() - } -} diff --git a/framework/base/src/api/vm_api.rs b/framework/base/src/api/vm_api.rs index 03358e0ded..c7cac0daa2 100644 --- a/framework/base/src/api/vm_api.rs +++ b/framework/base/src/api/vm_api.rs @@ -4,7 +4,6 @@ use super::{ StorageReadApiImpl, StorageWriteApi, }; -#[cfg(not(feature = "serde"))] pub trait VMApi: ManagedTypeApi + BlockchainApi @@ -38,40 +37,3 @@ pub trait VMApi: Self::storage_read_api_impl().storage_read_api_init(); } } - -#[cfg(feature = "serde")] -pub trait VMApi: - ManagedTypeApi - + BlockchainApi - + CallValueApi - + CryptoApi - + EndpointArgumentApi - + EndpointFinishApi - + ErrorApi - + LogApi - + SendApi - + StorageReadApi - + StorageWriteApi - + PrintApi - + CallTypeApi - + StorageMapperApi - + Clone // TODO: remove - + PartialEq // for helping derive PartialEq for managed types - + Eq - + Send - + Sync - + serde::ser::Serialize - + serde::de::DeserializeOwned -{ - /// Slightly hacky way of overriding the constructor for external view contracts. - /// - /// Only required for the tests, in production the meta crate makes sure to replace it. - /// - /// TODO: find a more robust and maybe extendable solution. - fn external_view_init_override() -> bool { - false - } - fn init_static() { - Self::storage_read_api_impl().storage_read_api_init(); - } -} diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index 869d6b59f8..a1ba0495d0 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -602,18 +602,6 @@ impl serde::Serialize for ManagedBuffer { } } -// #[cfg(feature = "serde")] -// impl<'de, M: ManagedTypeApi> serde::Deserialize<'de> for ManagedBuffer { -// fn deserialize(deserializer: D) -> Result -// where -// D: serde::Deserializer<'de>, -// { -// deserializer.deserialize_str(visitor) -// let s = alloc::string::String::deserialize(deserializer)?; -// Ok(ManagedBuffer::new_from_bytes(s.as_bytes())) -// } -// } - #[cfg(feature = "serde")] impl<'de, M: ManagedTypeApi> serde::Deserialize<'de> for ManagedBuffer { fn deserialize(deserializer: D) -> Result diff --git a/framework/meta-lib/src/contract/meta_config.rs b/framework/meta-lib/src/contract/meta_config.rs index aba7ef9445..6545f75de3 100644 --- a/framework/meta-lib/src/contract/meta_config.rs +++ b/framework/meta-lib/src/contract/meta_config.rs @@ -22,7 +22,7 @@ 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] = &["serde"]; +const WASM_ADAPTER_FEATURE_WHITELIST: &[&str] = &[]; #[derive(Debug)] pub struct MetaConfig { diff --git a/framework/wasm-adapter/Cargo.toml b/framework/wasm-adapter/Cargo.toml index 98eb14fcc1..bd7e34cb14 100644 --- a/framework/wasm-adapter/Cargo.toml +++ b/framework/wasm-adapter/Cargo.toml @@ -23,7 +23,6 @@ categories = [ [features] std = ["multiversx-sc/std"] -serde = ["multiversx-sc/serde"] [dependencies.multiversx-sc] version = "=0.60.0" diff --git a/framework/wasm-adapter/src/api/vm_api_node.rs b/framework/wasm-adapter/src/api/vm_api_node.rs index f01f82a4df..56c29e44e2 100644 --- a/framework/wasm-adapter/src/api/vm_api_node.rs +++ b/framework/wasm-adapter/src/api/vm_api_node.rs @@ -38,23 +38,3 @@ impl HandleTypeInfo for VmApiImpl { type ManagedMapHandle = i32; } - -#[cfg(feature = "serde")] -impl multiversx_sc::serde::Serialize for VmApiImpl { - fn serialize(&self, _serializer: S) -> Result - where - S: multiversx_sc::serde::Serializer, - { - unreachable!() - } -} - -#[cfg(feature = "serde")] -impl<'de> multiversx_sc::serde::de::Deserialize<'de> for VmApiImpl { - fn deserialize(_deserializer: D) -> Result - where - D: multiversx_sc::serde::Deserializer<'de>, - { - unreachable!() - } -} \ No newline at end of file From c45ce97fdfb8a32f86302973ad0b8d7987961bec Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 26 Aug 2025 19:24:02 +0300 Subject: [PATCH 5/7] fmt --- contracts/feature-tests/serde-features/src/serde_features.rs | 2 +- framework/base/src/api/external_view/ev_wrapper.rs | 1 - framework/base/src/api/uncallable/vm_api_uncallable.rs | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/feature-tests/serde-features/src/serde_features.rs b/contracts/feature-tests/serde-features/src/serde_features.rs index 983520b2d8..0a5238e675 100644 --- a/contracts/feature-tests/serde-features/src/serde_features.rs +++ b/contracts/feature-tests/serde-features/src/serde_features.rs @@ -20,7 +20,7 @@ pub struct SerdeStruct2 { } #[derive(Serialize, Deserialize)] -#[serde(bound = "M: ManagedTypeApi")] +#[serde(bound = "M: ManagedTypeApi")] pub struct ManagedSerdeStruct { mb: ManagedBuffer, } diff --git a/framework/base/src/api/external_view/ev_wrapper.rs b/framework/base/src/api/external_view/ev_wrapper.rs index 8f012a233f..6b88231e5b 100644 --- a/framework/base/src/api/external_view/ev_wrapper.rs +++ b/framework/base/src/api/external_view/ev_wrapper.rs @@ -189,4 +189,3 @@ where } impl Eq for ExternalViewApi where A: VMApi {} - diff --git a/framework/base/src/api/uncallable/vm_api_uncallable.rs b/framework/base/src/api/uncallable/vm_api_uncallable.rs index 4dba88a17a..1b6a610099 100644 --- a/framework/base/src/api/uncallable/vm_api_uncallable.rs +++ b/framework/base/src/api/uncallable/vm_api_uncallable.rs @@ -27,4 +27,3 @@ impl HandleTypeInfo for UncallableApi { type ManagedMapHandle = i32; } - From ff5557538c2b6ee9ade8715a9be90f1f440f19d3 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 26 Aug 2025 20:21:43 +0300 Subject: [PATCH 6/7] wasm cargo toml features fix --- framework/meta-lib/src/contract/meta_config.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/framework/meta-lib/src/contract/meta_config.rs b/framework/meta-lib/src/contract/meta_config.rs index 6545f75de3..bc969e6557 100644 --- a/framework/meta-lib/src/contract/meta_config.rs +++ b/framework/meta-lib/src/contract/meta_config.rs @@ -78,15 +78,19 @@ impl MetaConfig { let mut framework_dependency = main_cargo_toml_contents .dependency_raw_value(FRAMEWORK_NAME_BASE) .expect("missing framework dependency in Cargo.toml"); - if contract.settings.std { - framework_dependency.features.insert("std".to_owned()); - } + + // filter original multiversx_sc feature flags (none at the moment) framework_dependency.features = framework_dependency .features .into_iter() .filter(|f| WASM_ADAPTER_FEATURE_WHITELIST.contains(&f.as_str())) .collect(); + // add std feature flag + if contract.settings.std { + framework_dependency.features.insert("std".to_owned()); + } + let cargo_toml_data = WasmCargoTomlData { name: contract.wasm_crate_name.clone(), edition: main_cargo_toml_contents.package_edition(), From 18eb48c60aac693898d104cdcc4c7a5fb5899e9a Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Tue, 26 Aug 2025 20:21:57 +0300 Subject: [PATCH 7/7] clippy fix --- framework/base/src/types/managed/basic/managed_buffer.rs | 5 +++-- framework/meta-lib/src/contract/meta_config.rs | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index a1ba0495d0..4e0673bdd6 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -597,8 +597,9 @@ impl serde::Serialize for ManagedBuffer { S: serde::Serializer, { let bytes = self.to_boxed_bytes(); - let s = str::from_utf8(bytes.as_slice()).map_err(|err| serde::ser::Error::custom(err))?; - serializer.serialize_str(s) + let s = alloc::string::String::from_utf8(bytes.into_vec()) + .map_err(serde::ser::Error::custom)?; + serializer.serialize_str(&s) } } diff --git a/framework/meta-lib/src/contract/meta_config.rs b/framework/meta-lib/src/contract/meta_config.rs index bc969e6557..253aa689a3 100644 --- a/framework/meta-lib/src/contract/meta_config.rs +++ b/framework/meta-lib/src/contract/meta_config.rs @@ -80,11 +80,9 @@ impl MetaConfig { .expect("missing framework dependency in Cargo.toml"); // filter original multiversx_sc feature flags (none at the moment) - framework_dependency.features = framework_dependency + framework_dependency .features - .into_iter() - .filter(|f| WASM_ADAPTER_FEATURE_WHITELIST.contains(&f.as_str())) - .collect(); + .retain(|f| WASM_ADAPTER_FEATURE_WHITELIST.contains(&f.as_str())); // add std feature flag if contract.settings.std {