From b5a23d3873c2aae763575ebe760031d075a09edd Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Sun, 4 Dec 2022 14:38:44 -0800 Subject: [PATCH] only subtype checking for reference type (#395) * only subtype checking for reference type; For opt type, add error type handling * use unsafe for opt --- Cargo.lock | 436 +++++++++++++++++++------------------ rust/candid/Cargo.toml | 2 +- rust/candid/src/de.rs | 184 ++++++++++------ rust/candid/src/error.rs | 10 + rust/candid/tests/serde.rs | 108 +++++++-- test/construct.test.did | 15 +- test/prim.test.did | 13 +- test/subtypes.test.did | 164 ++++++++++++++ tools/didc/Cargo.toml | 2 +- 9 files changed, 631 insertions(+), 303 deletions(-) create mode 100644 test/subtypes.test.did diff --git a/Cargo.lock b/Cargo.lock index 5d7f4aeb..ea694ef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,15 +29,15 @@ checksum = "939d59666dd9a7964a3a5312b9d24c9c107630752ee64f2dd5038189a23fe331" dependencies = [ "abnf", "indexmap", - "itertools 0.10.3", + "itertools 0.10.5", "pretty 0.11.3", ] [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -68,15 +68,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.60" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "arbitrary" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7924531f38b1970ff630f03eb20a2fde69db5c590c93b0f3482e95dcc5fd60" +checksum = "29d47fbf90d5149a107494b15a7dc8d69b351be2db3bb9691740e88ec17fd880" [[package]] name = "arrayvec" @@ -101,7 +101,7 @@ checksum = "c98233c6673d8601ab23e77eb38f999c51100d46c5703b17288c57fddf3a1ffe" dependencies = [ "bstr", "doc-comment", - "predicates 2.1.1", + "predicates 2.1.4", "predicates-core", "predicates-tree", "wait-timeout", @@ -148,9 +148,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d9672209df1714ee804b1f4d4f68c8eb2a90b1f7a07acf472f88ce198ef1fed" dependencies = [ "either", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -205,9 +205,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "byteorder" @@ -217,7 +217,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "candid" -version = "0.8.4" +version = "0.9.0-beta" dependencies = [ "anyhow", "arbitrary", @@ -248,7 +248,7 @@ dependencies = [ "serde_dhall", "serde_json", "serde_test", - "sha2 0.10.2", + "sha2 0.10.6", "test-generator", "thiserror", ] @@ -258,9 +258,9 @@ name = "candid_derive" version = "0.5.0" dependencies = [ "lazy_static", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] @@ -333,14 +333,14 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.22" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "bitflags", "clap_lex", "indexmap", - "textwrap 0.15.1", + "textwrap 0.16.0", ] [[package]] @@ -364,22 +364,22 @@ dependencies = [ [[package]] name = "console" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", "terminal_size", "winapi", ] [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" dependencies = [ "libc", ] @@ -403,9 +403,9 @@ dependencies = [ "atty", "cast", "ciborium", - "clap 3.2.22", + "clap 3.2.23", "criterion-plot", - "itertools 0.10.3", + "itertools 0.10.5", "lazy_static", "num-traits", "oorandom", @@ -426,7 +426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools 0.10.3", + "itertools 0.10.5", ] [[package]] @@ -452,26 +452,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", - "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -527,14 +525,14 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df7c81d16870879ef530b07cef32bc6088f98937ab4168106cc8e382a05146bf" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] name = "didc" -version = "0.1.6" +version = "0.2.0" dependencies = [ "anyhow", "candid", @@ -575,11 +573,11 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer 0.10.2", + "block-buffer 0.10.3", "crypto-common", ] @@ -612,9 +610,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "elsa" @@ -694,11 +692,10 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] @@ -714,9 +711,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -731,9 +728,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "goldenfile" -version = "1.4.3" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03bd0e9c2ea26ce269d37016d6b95556bbfa544cbbbdeff40102ac54121c990b" +checksum = "bf1e66766a6a6960b997e03eeaa212b05b87e0275ede54eb3fe2ec1c6071305b" dependencies = [ "similar-asserts", "tempfile", @@ -777,9 +774,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "home" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654" +checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" dependencies = [ "winapi", ] @@ -792,11 +789,10 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -809,9 +805,9 @@ checksum = "7a46645bbd70538861a90d0f26c31537cdf1e44aae99a794fb75a664b70951bc" [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -837,24 +833,24 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -870,7 +866,7 @@ dependencies = [ "bit-set", "diff", "ena", - "itertools 0.10.3", + "itertools 0.10.5", "lalrpop-util", "petgraph", "pico-args", @@ -879,7 +875,7 @@ dependencies = [ "string_cache", "term", "tiny-keccak", - "unicode-xid 0.2.3", + "unicode-xid 0.2.4", ] [[package]] @@ -905,15 +901,15 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.127" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -945,18 +941,12 @@ checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" dependencies = [ "beef", "fnv", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", "regex-syntax", - "syn 1.0.99", + "syn 1.0.105", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" version = "2.5.0" @@ -965,9 +955,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] @@ -1033,9 +1023,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", @@ -1057,16 +1047,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] name = "once_cell" -version = "1.13.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "oorandom" @@ -1082,9 +1072,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "os_str_bytes" -version = "6.3.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "parking_lot" @@ -1098,9 +1088,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if", "libc", @@ -1111,21 +1101,21 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.2.1" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8" +checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" dependencies = [ "thiserror", "ucd-trie", @@ -1133,9 +1123,9 @@ dependencies = [ [[package]] name = "pest_consume" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb7c2ab7ca422b1f9b9e821c96667dc6675885c8a986cb379f7fac36b229085" +checksum = "79447402d15d18e7142e14c72f2e63fa3d155be1bc5b70b3ccbb610ac55f536b" dependencies = [ "pest", "pest_consume_macros", @@ -1148,16 +1138,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d8630a7a899cb344ec1c16ba0a6b24240029af34bdc0a21f84e411d7f793f29" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] name = "pest_derive" -version = "2.2.1" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13570633aff33c6d22ce47dd566b10a3b9122c2fe9d8e7501895905be532b91" +checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344" dependencies = [ "pest", "pest_generator", @@ -1165,26 +1155,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.2.1" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c567e5702efdc79fb18859ea74c3eb36e14c43da7b8c1f098a4ed6514ec7a0" +checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] name = "pest_meta" -version = "2.2.1" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb32be5ee3bbdafa8c7a18b0a8a8d962b66cfa2ceee4037f49267a50ee821fe" +checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20" dependencies = [ "once_cell", "pest", - "sha-1", + "sha1", ] [[package]] @@ -1214,9 +1204,9 @@ checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" [[package]] name = "plotters" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9428003b84df1496fb9d6eeee9c5f8145cb41ca375eb0dad204328888832811f" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -1233,18 +1223,18 @@ checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0918736323d1baff32ee0eade54984f6f201ad7e97d5cfb5d6ab4a358529615" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "precomputed-hash" @@ -1267,26 +1257,26 @@ dependencies = [ [[package]] name = "predicates" -version = "2.1.1" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" +checksum = "f54fc5dc63ed3bbf19494623db4f3af16842c0d975818e469022d09e53f0aa05" dependencies = [ "difflib", - "itertools 0.10.3", + "itertools 0.10.5", "predicates-core", ] [[package]] name = "predicates-core" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" +checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2" [[package]] name = "predicates-tree" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" +checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d" dependencies = [ "predicates-core", "termtree", @@ -1338,9 +1328,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", "version_check", ] @@ -1350,7 +1340,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", "version_check", ] @@ -1366,9 +1356,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] @@ -1388,7 +1378,7 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", ] [[package]] @@ -1414,20 +1404,19 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" dependencies = [ - "autocfg", "crossbeam-deque", "either", "rayon-core", @@ -1435,9 +1424,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1467,9 +1456,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -1484,9 +1473,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -1526,9 +1515,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.143" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" dependencies = [ "serde_derive", ] @@ -1554,13 +1543,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.143" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] @@ -1578,9 +1567,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "itoa", "ryu", @@ -1589,22 +1578,22 @@ dependencies = [ [[package]] name = "serde_test" -version = "1.0.145" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c17d2112159132660b4c5399e274f676fb75a2f8d70b7468f18f045b71138ed" +checksum = "5b8178223189ca1d189513acd64ed130a3a2e7c76247a19ca11680498b097558" dependencies = [ "serde", ] [[package]] -name = "sha-1" -version = "0.10.0" +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] @@ -1622,20 +1611,20 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest 0.10.6", ] [[package]] name = "similar" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" dependencies = [ "bstr", "unicode-segmentation", @@ -1659,9 +1648,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "stable_deref_trait" @@ -1707,9 +1696,9 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] @@ -1725,11 +1714,11 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.99" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", "unicode-ident", ] @@ -1780,9 +1769,9 @@ dependencies = [ [[package]] name = "termtree" -version = "0.2.4" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" +checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8" [[package]] name = "test-generator" @@ -1807,28 +1796,28 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", ] [[package]] @@ -1888,9 +1877,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicode-bidi" @@ -1900,30 +1889,30 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -1933,19 +1922,18 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -1989,9 +1977,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1999,24 +1987,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote 1.0.21", "wasm-bindgen-macro-support", @@ -2024,28 +2012,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.43", + "proc-macro2 1.0.47", "quote 1.0.21", - "syn 1.0.99", + "syn 1.0.105", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -2084,43 +2072,57 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/rust/candid/Cargo.toml b/rust/candid/Cargo.toml index 2065b28d..e17c93b1 100644 --- a/rust/candid/Cargo.toml +++ b/rust/candid/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "candid" -version = "0.8.4" +version = "0.9.0-beta" edition = "2018" authors = ["DFINITY Team"] description = "Candid is an interface description language (IDL) for interacting with canisters running on the Internet Computer." diff --git a/rust/candid/src/de.rs b/rust/candid/src/de.rs index b93c2ce3..4989ff9c 100644 --- a/rust/candid/src/de.rs +++ b/rust/candid/src/de.rs @@ -51,13 +51,13 @@ impl<'de> IDLDeserialize<'de> { { let expected_type = self.de.table.trace_type(&expected_type)?; if self.de.types.is_empty() { - if matches!(expected_type, Type::Opt(_) | Type::Reserved | Type::Null) { + if matches!(expected_type, Type::Opt(_) | Type::Reserved) { self.de.expect_type = expected_type; - self.de.wire_type = Type::Null; + self.de.wire_type = Type::Reserved; return T::deserialize(&mut self.de); } else { return Err(Error::msg(format!( - "No more values on the wire, the expected type {} is not opt, reserved or null", + "No more values on the wire, the expected type {} is not opt or reserved", expected_type ))); } @@ -71,15 +71,6 @@ impl<'de> IDLDeserialize<'de> { expected_type.clone() }; self.de.wire_type = ty.clone(); - self.de - .check_subtype() - .with_context(|| self.de.dump_state()) - .with_context(|| { - format!( - "Fail to decode argument {} from {} to {}", - ind, ty, expected_type - ) - })?; let v = T::deserialize(&mut self.de) .with_context(|| self.de.dump_state()) @@ -129,6 +120,21 @@ macro_rules! assert { }}; } +macro_rules! check { + ( false ) => {{ + return Err(Error::Subtype(format!( + "Type mismatch at {}:{}", + file!(), + line!() + ))); + }}; + ($exp:expr, $msg:expr) => {{ + if !$exp { + return Err(Error::Subtype($msg.to_string())); + } + }}; +} + struct Deserializer<'de> { input: Cursor<&'de [u8]>, table: TypeEnv, @@ -203,7 +209,8 @@ impl<'de> Deserializer<'de> { "{} is not a subtype of {}", self.wire_type, self.expect_type, ) - })?; + }) + .map_err(Error::subtype)?; Ok(()) } fn unroll_type(&mut self) -> Result<()> { @@ -244,8 +251,12 @@ impl<'de> Deserializer<'de> { .0 .try_into() .map_err(Error::msg)?), - // We already did subtype checking before deserialize, so this is unreachable code - _ => assert!(false), + t => { + return Err(Error::subtype(format!( + "{} cannot be deserialized to int", + t + ))) + } }; bytes.extend_from_slice(&int.0.to_signed_bytes_le()); visitor.visit_byte_buf(bytes) @@ -255,7 +266,10 @@ impl<'de> Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(self.expect_type == Type::Nat && self.wire_type == Type::Nat); + check!( + self.expect_type == Type::Nat && self.wire_type == Type::Nat, + "nat" + ); let mut bytes = vec![1u8]; let nat = Nat::decode(&mut self.input).map_err(Error::msg)?; bytes.extend_from_slice(&nat.0.to_bytes_le()); @@ -266,7 +280,10 @@ impl<'de> Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(self.expect_type == Type::Principal && self.wire_type == Type::Principal); + check!( + self.expect_type == Type::Principal && self.wire_type == Type::Principal, + "principal" + ); let mut bytes = vec![2u8]; let id = PrincipalBytes::read(&mut self.input)?.inner; bytes.extend_from_slice(&id); @@ -284,7 +301,7 @@ impl<'de> Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(matches!(self.wire_type, Type::Service(_))); + self.check_subtype()?; let mut bytes = vec![4u8]; let id = PrincipalBytes::read(&mut self.input)?.inner; bytes.extend_from_slice(&id); @@ -295,7 +312,7 @@ impl<'de> Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(matches!(self.wire_type, Type::Func(_))); + self.check_subtype()?; if !BoolValue::read(&mut self.input)?.0 { return Err(Error::msg("Opaque reference not supported")); } @@ -315,6 +332,22 @@ impl<'de> Deserializer<'de> { { Err(Error::msg("Cannot decode empty type")) } + unsafe fn recoverable_visit_some<'a, V>(&'a mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + use de::Deserializer; + let v = std::ptr::read(&visitor); + let self_ptr = std::ptr::read(&self); + match v.visit_some(self_ptr) { + Ok(v) => Ok(v), + Err(Error::Subtype(_)) => { + self.deserialize_ignored_any(serde::de::IgnoredAny)?; + visitor.visit_none() + } + Err(e) => Err(e), + } + } } macro_rules! primitive_impl { @@ -323,9 +356,8 @@ macro_rules! primitive_impl { fn [](self, visitor: V) -> Result where V: Visitor<'de> { self.unroll_type()?; - assert!(self.expect_type == $type && self.wire_type == $type); + check!(self.expect_type == $type && self.wire_type == $type, stringify!($type)); let val = self.input.$($value)*().map_err(|_| Error::msg(format!("Cannot read {} value", stringify!($type))))?; - //let val: $ty = self.input.read_le()?; visitor.[](val) } } @@ -417,7 +449,12 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { let nat = Nat::decode(&mut self.input).map_err(Error::msg)?; nat.0.try_into().map_err(Error::msg)? } - _ => assert!(false), + t => { + return Err(Error::subtype(format!( + "{} cannot be deserialized to int", + t + ))) + } }; visitor.visit_i128(value) } @@ -427,7 +464,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { { use std::convert::TryInto; self.unroll_type()?; - assert!(self.expect_type == Type::Nat && self.wire_type == Type::Nat); + check!( + self.expect_type == Type::Nat && self.wire_type == Type::Nat, + "nat" + ); let nat = Nat::decode(&mut self.input).map_err(Error::msg)?; let value: u128 = nat.0.try_into().map_err(Error::msg)?; visitor.visit_u128(value) @@ -437,7 +477,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(self.expect_type == Type::Null && self.wire_type == Type::Null); + check!( + self.expect_type == Type::Null && self.wire_type == Type::Null, + "unit" + ); visitor.visit_unit() } fn deserialize_bool(self, visitor: V) -> Result @@ -445,7 +488,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(self.expect_type == Type::Bool && self.wire_type == Type::Bool); + check!( + self.expect_type == Type::Bool && self.wire_type == Type::Bool, + "bool" + ); let res = BoolValue::read(&mut self.input)?; visitor.visit_bool(res.0) } @@ -454,7 +500,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(self.expect_type == Type::Text && self.wire_type == Type::Text); + check!( + self.expect_type == Type::Text && self.wire_type == Type::Text, + "text" + ); let len = Len::read(&mut self.input)?.0; let bytes = self.borrow_bytes(len)?.to_owned(); let value = String::from_utf8(bytes).map_err(Error::msg)?; @@ -465,7 +514,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { V: Visitor<'de>, { self.unroll_type()?; - assert!(self.expect_type == Type::Text && self.wire_type == Type::Text); + check!( + self.expect_type == Type::Text && self.wire_type == Type::Text, + "text" + ); let len = Len::read(&mut self.input)?.0; let slice = self.borrow_bytes(len)?; let value: &str = std::str::from_utf8(slice).map_err(Error::msg)?; @@ -494,28 +546,21 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { self.wire_type = *t1.clone(); self.expect_type = *t2.clone(); if BoolValue::read(&mut self.input)?.0 { - if self.check_subtype().is_ok() { - visitor.visit_some(self) - } else { - self.deserialize_ignored_any(serde::de::IgnoredAny)?; - visitor.visit_none() - } + unsafe { self.recoverable_visit_some(visitor) } } else { visitor.visit_none() } } (_, Type::Opt(t2)) => { self.expect_type = self.table.trace_type(t2)?; - if !matches!(self.expect_type, Type::Null | Type::Reserved | Type::Opt(_)) - && self.check_subtype().is_ok() - { - visitor.visit_some(self) + if !matches!(self.expect_type, Type::Null | Type::Reserved | Type::Opt(_)) { + unsafe { self.recoverable_visit_some(visitor) } } else { self.deserialize_ignored_any(serde::de::IgnoredAny)?; visitor.visit_none() } } - (_, _) => assert!(false), + (_, _) => check!(false), } } fn deserialize_seq(self, visitor: V) -> Result @@ -533,9 +578,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { (Type::Record(e), Type::Record(w)) => { let expect = e.clone().into(); let wire = w.clone().into(); - assert!(self.expect_type.is_tuple()); + check!(self.expect_type.is_tuple(), "seq_tuple"); if !self.wire_type.is_tuple() { - return Err(Error::msg(format!( + return Err(Error::subtype(format!( "{} is not a tuple type", self.wire_type ))); @@ -544,19 +589,18 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { visitor.visit_seq(Compound::new(self, Style::Struct { expect, wire }))?; Ok(value) } - (Type::Record(_), Type::Empty) => Err(Error::msg("Cannot decode empty type")), - _ => assert!(false), + _ => check!(false), } } fn deserialize_byte_buf>(self, visitor: V) -> Result { self.unroll_type()?; - assert!( + check!( self.expect_type == Type::Vec(Box::new(Type::Nat8)) - && self.wire_type == Type::Vec(Box::new(Type::Nat8)) + && self.wire_type == Type::Vec(Box::new(Type::Nat8)), + "vec nat8" ); let len = Len::read(&mut self.input)?.0; let bytes = self.borrow_bytes(len)?.to_owned(); - //let bytes = Bytes::read(&mut self.input)?.inner; visitor.visit_byte_buf(bytes) } fn deserialize_bytes>(self, visitor: V) -> Result { @@ -568,7 +612,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { let slice = self.borrow_bytes(len)?; visitor.visit_borrowed_bytes(slice) } - _ => Err(Error::msg("bytes only takes principal or vec nat8")), + _ => Err(Error::subtype("bytes only takes principal or vec nat8")), } } fn deserialize_map(self, visitor: V) -> Result @@ -580,7 +624,6 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { (Type::Vec(ref e), Type::Vec(ref w)) => { let e = self.table.trace_type(e)?; let w = self.table.trace_type(w)?; - let len = Len::read(&mut self.input)?.0; match (e, w) { (Type::Record(ref e), Type::Record(ref w)) => match (&e[..], &w[..]) { ( @@ -601,14 +644,15 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { ) => { let expect = (ek.clone(), ev.clone()); let wire = (wk.clone(), wv.clone()); + let len = Len::read(&mut self.input)?.0; visitor.visit_map(Compound::new(self, Style::Map { len, expect, wire })) } - _ => Err(Error::msg("expect a key-value pair")), + _ => Err(Error::subtype("expect a key-value pair")), }, - _ => Err(Error::msg("expect a key-value pair")), + _ => Err(Error::subtype("expect a key-value pair")), } } - _ => assert!(false), + _ => check!(false), } } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result @@ -646,8 +690,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { visitor.visit_map(Compound::new(self, Style::Struct { expect, wire }))?; Ok(value) } - (Type::Record(_), Type::Empty) => Err(Error::msg("Cannot decode empty type")), - _ => assert!(false), + _ => check!(false), } } fn deserialize_enum( @@ -662,6 +705,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { self.unroll_type()?; match (&self.expect_type, &self.wire_type) { (Type::Variant(e), Type::Variant(w)) => { + let old_pos = self.input.position(); let index = Len::read(&mut self.input)?.0; let len = w.len(); if index >= len { @@ -671,14 +715,16 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { ))); } let wire = w[index].clone(); - let expect = e - .iter() - .find(|f| f.id == wire.id) - .ok_or_else(|| Error::msg(format!("Unknown variant field {}", wire.id)))? - .clone(); + let expect = match e.iter().find(|f| f.id == wire.id) { + Some(v) => v.clone(), + None => { + self.input.set_position(old_pos); + return Err(Error::subtype(format!("Unknown variant field {}", wire.id))); + } + }; visitor.visit_enum(Compound::new(self, Style::Enum { expect, wire })) } - _ => assert!(false), + _ => check!(false), } } fn deserialize_identifier(self, visitor: V) -> Result @@ -762,7 +808,7 @@ impl<'de, 'a> de::SeqAccess<'de> for Compound<'a, 'de> { self.de.wire_type = wire.pop_front().map(|f| f.ty).unwrap_or(Type::Reserved); seed.deserialize(&mut *self.de).map(Some) } - _ => Err(Error::msg("expect vector or tuple")), + _ => Err(Error::subtype("expect vector or tuple")), } } } @@ -789,8 +835,17 @@ impl<'de, 'a> de::MapAccess<'de> for Compound<'a, 'de> { } Ordering::Less => { // by subtyping rules, expect_type can only be opt, reserved or null. - self.de.set_field_name(e.id.clone()); - self.de.expect_type = expect.pop_front().unwrap().ty; + let field = e.id.clone(); + self.de.set_field_name(field.clone()); + let expect = expect.pop_front().unwrap().ty; + self.de.expect_type = self.de.table.trace_type(&expect)?; + check!( + matches!( + self.de.expect_type, + Type::Opt(_) | Type::Reserved | Type::Null + ), + format!("field {} is not optional field", field) + ); self.de.wire_type = Type::Reserved; } Ordering::Greater => { @@ -874,7 +929,7 @@ impl<'de, 'a> de::EnumAccess<'de> for Compound<'a, 'de> { let field = seed.deserialize(&mut *self.de)?; Ok((field, self)) } - _ => Err(Error::msg("expect enum")), + _ => Err(Error::subtype("expect enum")), } } } @@ -883,7 +938,10 @@ impl<'de, 'a> de::VariantAccess<'de> for Compound<'a, 'de> { type Error = Error; fn unit_variant(self) -> Result<()> { - assert!(self.de.expect_type == Type::Null && self.de.wire_type == Type::Null); + check!( + self.de.expect_type == Type::Null && self.de.wire_type == Type::Null, + "unit_variant" + ); Ok(()) } diff --git a/rust/candid/src/error.rs b/rust/candid/src/error.rs index d0f77add..f3ad3316 100644 --- a/rust/candid/src/error.rs +++ b/rust/candid/src/error.rs @@ -19,6 +19,9 @@ pub enum Error { #[error("binary parser error: {}", .0.get(0).map(|f| format!("{} at byte offset {}", f.message, f.range.start/2)).unwrap_or_else(|| "io error".to_string()))] Binread(Vec>), + #[error("Subtyping error: {0}")] + Subtype(String), + #[error(transparent)] Custom(#[from] anyhow::Error), } @@ -27,6 +30,9 @@ impl Error { pub fn msg(msg: T) -> Self { Error::Custom(anyhow::anyhow!(msg.to_string())) } + pub fn subtype(msg: T) -> Self { + Error::Subtype(msg.to_string()) + } pub fn report(&self) -> Diagnostic<()> { match self { Error::Parse(e) => { @@ -57,6 +63,7 @@ impl Error { let diag = Diagnostic::error().with_message("decoding error"); diag.with_labels(labels.to_vec()) } + Error::Subtype(e) => Diagnostic::error().with_message(e), Error::Custom(e) => Diagnostic::error().with_message(e.to_string()), } } @@ -135,6 +142,9 @@ impl de::Error for Error { fn custom(msg: T) -> Self { Error::msg(format!("Deserialize error: {}", msg)) } + fn invalid_type(_: de::Unexpected<'_>, exp: &dyn de::Expected) -> Self { + Error::Subtype(format!("{}", exp)) + } } impl From for Error { diff --git a/rust/candid/tests/serde.rs b/rust/candid/tests/serde.rs index 2d28e15b..7d528918 100644 --- a/rust/candid/tests/serde.rs +++ b/rust/candid/tests/serde.rs @@ -61,10 +61,7 @@ fn test_integer() { Int::parse(b"-60000000000000000").unwrap(), "4449444c00017c8080e88b96cab5957f", ); - check_error( - || test_decode(&hex("4449444c00017c2a"), &42i64), - "int is not a subtype of int64", - ); + check_error(|| test_decode(&hex("4449444c00017c2a"), &42i64), "Int64"); } #[test] @@ -136,7 +133,10 @@ fn test_reserved() { #[test] fn test_reference() { - use candid::{Func, Principal, Service}; + use candid::{ + types::{Function, Type}, + Func, Principal, Service, + }; let principal = Principal::from_text("w7x7r-cok77-xa").unwrap(); all_check(principal, "4449444c0001680103caffee"); all_check(Service { principal }, "4449444c01690001000103caffee"); @@ -147,6 +147,25 @@ fn test_reference() { }, "4449444c016a0000000100010103caffee066d6574686f64", ); + #[derive(Deserialize, PartialEq, Debug)] + struct CustomFunc(Func); + impl CandidType for CustomFunc { + fn _ty() -> Type { + Type::Func(Function { + args: vec![], + rets: vec![Type::Nat], + modes: vec![], + }) + } + fn idl_serialize( + &self, + _serializer: S, + ) -> Result<(), S::Error> { + unimplemented!() + } + } + let bytes = hex("4449444c016a00017f000100010100016d"); + test_decode(&bytes, &None::); } #[test] @@ -236,6 +255,61 @@ fn test_struct() { all_check(list, "4449444c026e016c02a0d2aca8047c90eddae70400010000"); } +#[test] +fn optional_fields() { + #[derive(PartialEq, Debug, Deserialize, CandidType)] + struct OldStruct { + bar: bool, + baz: Option, + } + #[derive(PartialEq, Debug, Deserialize, CandidType)] + enum Old { + Foo, + Bar(bool), + } + #[derive(PartialEq, Debug, Deserialize, CandidType)] + enum New { + Foo, + Bar(bool), + Baz(bool), + } + #[derive(PartialEq, Debug, Deserialize, CandidType)] + struct NewStruct { + foo: Option, + bar: bool, + baz: Option, + } + let bytes = encode(&OldStruct { + bar: true, + baz: Some(Old::Foo), + }); + test_decode( + &bytes, + &NewStruct { + foo: None, + bar: true, + baz: Some(New::Foo), + }, + ); + let bytes = encode(&NewStruct { + foo: Some(42), + bar: false, + baz: Some(New::Baz(true)), + }); + test_decode( + &bytes, + &OldStruct { + bar: false, + baz: None, + }, + ); + let bytes = encode(&New::Baz(false)); + check_error( + || test_decode(&bytes, &Old::Bar(false)), + "Unknown variant field", + ); +} + #[test] fn test_equivalent_types() { #[derive(PartialEq, Debug, Deserialize, CandidType)] @@ -320,10 +394,7 @@ fn test_extra_fields() { let bytes = encode(&E2::Foo); test_decode(&bytes, &Some(E2::Foo)); - check_error( - || test_decode(&bytes, &E1::Foo), - "Variant field 3_303_867 not found", - ); + test_decode(&bytes, &E1::Foo); } #[test] @@ -490,7 +561,7 @@ fn test_tuple() { &(Int::from(42), "💩"), ) }, - "field 1: text is only in the expected type", + "is not a tuple type", ); } @@ -509,7 +580,7 @@ fn test_variant() { check_error( || test_decode(&hex("4449444c016b02b4d3c9017fe6fdd5017f010000"), &Unit::Bar), - "Variant field 3_303_860 not found", + "Unknown variant field 3_303_860", ); let res: Result = Ok("good".to_string()); @@ -527,6 +598,17 @@ fn test_variant() { v, "4449444c036b03b3d3c90101bbd3c90102e6fdd5017f6c02007e017c6c02617c627d010000012a", ); + + let bytes = encode(&Some(E::Foo)); + test_decode(&bytes, &Some(Unit::Foo)); + let bytes = encode(&E::Baz { + a: 42.into(), + b: 42.into(), + }); + test_decode(&bytes, &None::); + let bytes = encode(&E::Bar(true, 42.into())); + test_decode(&bytes, &None::); + check_error(|| test_decode(&bytes, &Unit::Bar), "Subtyping error"); } #[test] @@ -609,12 +691,12 @@ fn test_multiargs() { Vec<(Int, &str)>, (Int, String), Option, - (), + candid::Reserved, candid::Reserved ) .unwrap(); assert_eq!(tuple.2, None); - assert_eq!(tuple.3, ()); + assert_eq!(tuple.3, candid::Reserved); assert_eq!(tuple.4, candid::Reserved); } diff --git a/test/construct.test.did b/test/construct.test.did index 397da032..a3911bd4 100644 --- a/test/construct.test.did +++ b/test/construct.test.did @@ -54,7 +54,7 @@ assert blob "DIDL\00\00" == "(null)" : (Opt) "op // vector assert blob "DIDL\01\6d\7c\01\00\00" == "(vec {})" : (vec int) "vec: empty"; -assert blob "DIDL\01\6d\7c\01\00\00" !: (vec int8) "vec: non subtype empty"; +assert blob "DIDL\01\6d\7c\01\00\00" : (vec int8) "vec: non subtype empty"; assert blob "DIDL\01\6d\7c\01\00\02\01\02" == "(vec { 1; 2 })" : (vec int) "vec"; assert blob "DIDL\01\6d\7b\01\00\02\01\02" == "(blob \"\\01\\02\")" : (vec nat8) "vec: blob"; assert blob "DIDL\01\6d\00\01\00\00" == "(vec {})" : (Vec) "vec: recursive vector"; @@ -139,10 +139,10 @@ assert "(variant {})" ! assert blob "DIDL\01\6b\00\01\00" !: (variant {}) "variant: no empty value"; assert blob "DIDL\01\6b\01\00\7f\01\00\00" == "(variant {0})" : (variant {0}) "variant: numbered field"; assert blob "DIDL\01\6b\01\00\7f\01\00\00\2a" !: (variant {0:int}) "variant: type mismatch"; -assert blob "DIDL\01\6b\02\00\7f\01\7c\01\00\01\2a" !: (variant {0:int; 1:int}) "variant: type mismatch in unused tag"; +assert blob "DIDL\01\6b\02\00\7f\01\7c\01\00\01\2a" : (variant {0:int; 1:int}) "variant: type mismatch in unused tag"; assert blob "DIDL\01\6b\01\00\7f\01\00\00" == "(variant {0})" : (variant {0;1}) "variant: ignore field"; -assert blob "DIDL\01\6b\02\00\7f\01\7f\01\00\00" !: (variant {0}) "variant {0;1} !<: variant {0}"; -assert blob "DIDL\01\6b\02\00\7f\01\7f\01\00\00" == "(null)" : (opt variant {0}) "variant {0;1} <: opt variant {0}"; +assert blob "DIDL\01\6b\02\00\7f\01\7f\01\00\00" : (variant {0}) "variant {0;1} <: variant {0}"; +assert blob "DIDL\01\6b\02\00\7f\01\7f\01\00\00" == "(opt variant {0})" : (opt variant {0}) "variant {0;1} <: opt variant {0}"; assert blob "DIDL\01\6b\02\00\7f\01\7f\01\00\01" == "(variant {1})" : (variant {0;1;2}) "variant: change index"; assert blob "DIDL\01\6b\01\00\7f\01\00\00" !: (variant {1}) "variant: missing field"; assert blob "DIDL\01\6b\01\00\7f\01\00\01" !: (variant {0}) "variant: index out of range"; @@ -188,7 +188,7 @@ assert blob "DIDL\02\6b\02\d1\a7\cf\02\7f\f1\f3\92\8e\04\01\6c\02\a0\d2\ac\a8\04 == "(variant { cons = record { head = 1; tail = variant { cons = record { head = 2; tail = variant { nil } } } } })" : (VariantList) "variant: list"; assert blob "DIDL\02\6b\02\d1\a7\cf\02\7f\f1\f3\92\8e\04\01\6c\02\a0\d2\ac\a8\04\7c\90\ed\da\e7\04\00\01\00\00" - == "(variant {nil}, null, null, null, null)" : (VariantList, opt VariantList, null, reserved, opt int) "variant: extra args"; + == "(variant {nil}, null, null, null, null)" : (VariantList, opt VariantList, opt empty, reserved, opt int) "variant: extra args"; assert blob "DIDL\02\6b\02\d1\a7\cf\02\7f\f1\f3\92\8e\04\01\6c\02\a0\d2\ac\a8\04\7c\90\ed\da\e7\04\00\01\00\00" !: (VariantList, opt int, vec int) "non-null extra args"; @@ -203,3 +203,8 @@ assert blob "DIDL\07\6c\07\c3\e3\aa\02\01\d3\e3\aa\02\7e\d5\e3\aa\02\02\db\e3\aa assert blob "DIDL\07\6c\07\c3\e3\aa\02\01\d3\e3\aa\02\7e\d5\e3\aa\02\02\db\e3\aa\02\01\a2\e5\aa\02\04\bb\f1\aa\02\06\86\8e\b7\02\75\6c\02\d3\e3\aa\02\7e\86\8e\b7\02\75\6b\02\d1\a7\cf\02\7f\f1\f3\92\8e\04\03\6c\02\a0\d2\ac\a8\04\7c\90\ed\da\e7\04\02\6e\05\6c\02\a0\d2\ac\a8\04\7c\90\ed\da\e7\04\04\6b\02\d3\e3\aa\02\7f\86\8e\b7\02\7f\01\00\01\0b\00\00\00\01\00\00\0a\00\00\00\01\14\00\00\2a\00\00\00" !: (record { foo: int; new_field: bool }) "new record field"; +// Future types +// This uses 0x67 for the “future type”; bump (well, decrement) once that +// becomes a concrete future type +//assert blob "DIDL\01\67\00\02\00\7e\00\00\01" == "(null, true)" : (opt empty,bool) "skipping minimal future type"; +//assert blob "DIDL\01\67\03ABC\02\00\7e\05\00hello\01" == "(null,true)" : (opt empty,bool) "skipping future type with data"; diff --git a/test/prim.test.did b/test/prim.test.did index 2fc1533e..eff4c832 100644 --- a/test/prim.test.did +++ b/test/prim.test.did @@ -1,7 +1,7 @@ /* Encoding tests for primitive types -Corresponding to spec version version 0.1.3 +Corresponding to spec version version 0.1.4 */ // fundamentally wrong @@ -19,11 +19,19 @@ assert blob "DIDL\00\01\7f" : () "Additional parameters are ignored"; assert blob "DIDL\00\01\6e" !: () "Not a primitive type"; assert blob "DIDL\00\01\5e" !: () "Out of range type"; +// Missing arguments +assert blob "DIDL\00\00" !: (nat) "missing argument: nat fails"; +assert blob "DIDL\00\00" !: (empty) "missing argument: empty fails"; +assert blob "DIDL\00\00" !: (null) "missing argument: null fails"; +assert blob "DIDL\00\00" == "(null)" : (opt empty) "missing argument: opt empty"; +assert blob "DIDL\00\00" == "(null)" : (opt null) "missing argument: opt null"; +assert blob "DIDL\00\00" == "(null)" : (opt nat) "missing argument: opt nat"; +assert blob "DIDL\00\00" == blob "DIDL\00\01\70" : (reserved) "missing argument: reserved"; + // primitive types assert blob "DIDL\00\01\7f" : (null); assert blob "DIDL\00\01\7e" !: (null) "wrong type"; assert blob "DIDL\00\01\7f\00" !: (null) "null: too long"; -assert blob "DIDL\00\00" : (null) "null: extra null values"; assert blob "DIDL\00\01\7e\00" == "(false)" : (bool) "bool: false"; assert blob "DIDL\00\01\7e\01" == "(true)" : (bool) "bool: true"; @@ -181,7 +189,6 @@ assert blob "DIDL\00\01\70" == blob "DIDL\00\01\7f" : (reserved) "reser assert blob "DIDL\00\01\70" == blob "DIDL\00\01\7e\01" : (reserved) "reserved from bool"; assert blob "DIDL\00\01\70" == blob "DIDL\00\01\7d\80\01" : (reserved) "reserved from nat"; assert blob "DIDL\00\01\70" == blob "DIDL\00\01\71\06Motoko" : (reserved) "reserved from text"; -assert blob "DIDL\00\00" : (reserved) "reserved extra value"; assert blob "DIDL\00\01\71\05Motoko" !: (reserved) "reserved from too short text"; assert blob "DIDL\00\01\71\03\e2\28\a1" !: (reserved) "reserved from invalid utf8 text"; diff --git a/test/subtypes.test.did b/test/subtypes.test.did new file mode 100644 index 00000000..6dc09d22 --- /dev/null +++ b/test/subtypes.test.did @@ -0,0 +1,164 @@ +/* +Encoding tests for subtype tests in decoders + +Corresponding to spec version version 0.1.4 + +This test file contains tests for the subtype check that decoders are expected +to perform upon references. + +The shortest way to trigger a test for `t1 <: t2` is to pass `(func () -> (t1))` +and decode at type `(opt func () -> (t2))`, and check if the result is a +`reference` or `null`. + +The patterns idioms here are thus + +assert blob "DIDL\01\6a\00\01XX00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (t2)) "t1 <: t2"; +assert blob "DIDL\01\6a\00\01XX\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (t2)) "t1 (t2)) "t1 <: t2"; +assert blob "DIDL\02\6a\00\01\01\00XX\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (t2)) "t1 (null)) "null <: null"; +assert blob "DIDL\01\6a\00\01\7e\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (bool)) "bool <: bool"; +assert blob "DIDL\01\6a\00\01\7d\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (nat)) "nat <: nat"; +assert blob "DIDL\01\6a\00\01\7c\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (int)) "int <: int"; + +// more basic cases +assert blob "DIDL\01\6a\00\01\7d\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (int)) "nat <: int"; +assert blob "DIDL\01\6a\00\01\7f\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (nat)) "int (nat8)) "nat (nat)) "nat8 (opt bool)) "nat <: opt bool"; +assert blob "DIDL\02\6a\00\01\01\00\6e\7e\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (opt bool)) "opt bool <: opt bool"; +assert blob "DIDL\01\6a\00\01\7e\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (opt bool)) "bool <: opt bool"; +assert blob "DIDL\02\6a\00\01\01\00\6e\01\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (opt opt nat)) "µ opt <: opt opt nat"; + +// optional record fields +assert blob "DIDL\02\6a\00\01\01\00\6c\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (record {})) "record {} <: record {}"; +assert blob "DIDL\02\6a\00\01\01\00\6c\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (record { a : opt empty })) "record {} <: record { a : opt empty }"; +assert blob "DIDL\02\6a\00\01\01\00\6c\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (record { a : opt null })) "record {} <: record { a : opt null }"; +assert blob "DIDL\02\6a\00\01\01\00\6c\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (record { a : reserved })) "record {} <: record { a : reserved }"; +assert blob "DIDL\02\6a\00\01\01\00\6c\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (record { a : empty })) "record {} (record { a : nat })) "record {} (record { a : null })) "record {} (func () -> ())) "func () -> () <: func () -> ()"; +assert blob "DIDL\02\6a\00\01\01\00\6a\00\00\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (func () -> (opt empty))) "func () -> () <: func () -> (opt empty)"; +assert blob "DIDL\02\6a\00\01\01\00\6a\00\00\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (func () -> (opt null))) "func () -> () <: func () -> (opt null)"; +assert blob "DIDL\02\6a\00\01\01\00\6a\00\00\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (func () -> (reserved))) "func () -> () <: func () -> (reserved)"; +assert blob "DIDL\02\6a\00\01\01\00\6a\00\00\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (func () -> (empty))) "func () -> () (empty)"; +assert blob "DIDL\02\6a\00\01\01\00\6a\00\00\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (func () -> (nat))) "func () -> () (nat)"; +assert blob "DIDL\02\6a\00\01\01\00\6a\00\00\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (func () -> (null))) "func () -> () (null)"; + +// optional func arguments +assert blob "DIDL\03\6a\00\01\01\00\6a\01\02\00\00\6e\6f\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (func () -> ())) "func (opt empty) -> () <: func () -> ()"; +assert blob "DIDL\03\6a\00\01\01\00\6a\01\02\00\00\6e\7f\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (func () -> ())) "func (opt null) -> () <: func () -> ()"; +assert blob "DIDL\02\6a\00\01\01\00\6a\01\70\00\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (func () -> ())) "func (reserved) -> () <: func () -> ()"; +assert blob "DIDL\02\6a\00\01\01\00\6a\01\6f\00\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (func () -> ())) "func (empty) -> () ()"; +assert blob "DIDL\02\6a\00\01\01\00\6a\01\7d\00\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (func () -> ())) "func (nat) -> () ()"; +assert blob "DIDL\02\6a\00\01\01\00\6a\01\7f\00\00\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (func () -> ())) "func (null) -> () ()"; + +// variants +assert blob "DIDL\02\6a\00\01\01\00\6b\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (variant {})) "variant {} <: variant {}"; +assert blob "DIDL\02\6a\00\01\01\00\6b\00\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (variant {0 : nat})) "variant {} <: variant {0 : nat}"; +assert blob "DIDL\02\6a\00\01\01\00\6b\01\00\7d\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (variant {0 : nat})) "variant {0 : nat} <: variant {0 : nat}"; +assert blob "DIDL\02\6a\00\01\01\00\6b\01\00\7e\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (variant {0 : nat})) "variant {0 : bool} (variant {1 : bool})) "variant {0 : bool} (EmptyRecord)) "(µ record) <: (µ record)"; +//assert blob "DIDL\02\6a\00\01\01\00\6c\01\00\01\01\00\01\01\00\01m" +// == "(null)" : (opt func () -> (empty)) "(µ record) (EmptyRecord)) "empty <: (µ record)"; +assert blob "DIDL\02\6a\00\01\01\00\6c\01\00\01\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (record {EmptyRecord})) "(µ record) <: record {µ record}"; +assert blob "DIDL\03\6a\00\01\01\00\6c\01\00\02\6c\01\00\02\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (EmptyRecord)) "record {µ record} <: (µ record)"; + +assert blob "DIDL\02\6a\00\01\01\00\6b\01\00\01\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (EmptyVariant)) "(µ variant) <: (µ variant)"; +assert blob "DIDL\02\6a\00\01\01\00\6b\01\00\01\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (empty)) "(µ variant) (EmptyVariant)) "empty <: (µ variant)"; +assert blob "DIDL\02\6a\00\01\01\00\6b\01\00\01\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (variant {0 : EmptyVariant})) "(µ variant) <: variant {µ variant}"; +assert blob "DIDL\03\6a\00\01\01\00\6b\01\00\02\6b\01\00\02\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (EmptyVariant)) "variant {µ variant} <: (µ variant)"; + +assert blob "DIDL\02\6a\00\01\01\00\6d\01\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (Vec)) "(µ vec) <: (µ vec)"; +assert blob "DIDL\02\6a\00\01\01\00\6d\01\01\00\01\01\00\01m" + == "(null)" : (opt func () -> (empty)) "(µ vec) (Vec)) "empty <: (µ vec)"; +assert blob "DIDL\02\6a\00\01\01\00\6d\01\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (vec Vec)) "(µ vec) <: vec {µ vec}"; +assert blob "DIDL\03\6a\00\01\01\00\6d\02\6d\02\01\00\01\01\00\01m" + == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (Vec)) "vec {µ vec} <: (µ vec)"; + +// future types +// This uses 0x67 for the “future type”; bump (well, decrement) once that +// becomes a concrete future type + +//assert blob "DIDL\02\6a\00\01\01\00\67\00\01\00\01\01\00\01m" +// == "(opt func \"aaaaa-aa\".m)" : (opt func () -> (opt empty)) "(future type) <: (opt empty)"; +//assert blob "DIDL\02\6a\00\01\01\00\67\00\01\00\01\01\00\01m" +// == "(null)" : (opt func () -> (nat)) "(future type) <: (nat)"; diff --git a/tools/didc/Cargo.toml b/tools/didc/Cargo.toml index 6cf8545b..f5210007 100644 --- a/tools/didc/Cargo.toml +++ b/tools/didc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "didc" -version = "0.1.6" +version = "0.2.0" authors = ["DFINITY Team"] edition = "2018"