From 30337723566e9ac18c1c8fb57688cb7d4e24ca03 Mon Sep 17 00:00:00 2001 From: Yan Chen <48968912+chenyan-dfinity@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:35:06 -0700 Subject: [PATCH] Misc fix (#469) * fix merge_init_types and instantiate_candid * flamegraph for upgrade * add pub for struct fields * impl CandidType for cmp::Reverse * changelog * fix --- .github/workflows/rust.yml | 2 +- Cargo.lock | 94 ++++++-------- Cargo.toml | 2 + Changelog.md | 13 ++ rust/candid/Cargo.toml | 2 +- rust/candid/src/bindings/rust.rs | 66 ++++++---- rust/candid/src/types/impls.rs | 15 +++ rust/candid/src/utils.rs | 2 + rust/candid/tests/assets/ok/escape.rs | 8 +- rust/candid/tests/assets/ok/example.rs | 24 ++-- rust/candid/tests/assets/ok/fieldnat.rs | 16 ++- rust/candid/tests/assets/ok/keyword.rs | 10 +- rust/candid/tests/assets/ok/management.rs | 150 +++++++++++----------- rust/candid/tests/assets/ok/recursion.rs | 4 +- rust/candid/tests/assets/ok/unicode.did | 7 +- rust/candid/tests/assets/ok/unicode.rs | 8 +- tools/ui/Cargo.lock | 2 +- tools/ui/Cargo.toml | 1 + tools/ui/src/candid.ts | 5 +- tools/ui/src/didjs/lib.rs | 3 +- 20 files changed, 237 insertions(+), 197 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 15b86074..b50037a8 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -32,6 +32,6 @@ jobs: - name: fmt run: cargo fmt -v -- --check - name: lint - run: cargo clippy --tests -- -D clippy::all + run: cargo clippy --features all --tests -- -D clippy::all - name: doc run: cargo doc diff --git a/Cargo.lock b/Cargo.lock index d9104229..3e9c4bf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -257,7 +257,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "candid" -version = "0.9.7" +version = "0.9.8" dependencies = [ "anyhow", "arbitrary", @@ -282,7 +282,7 @@ dependencies = [ "num-traits", "num_enum", "paste", - "pretty 0.12.1", + "pretty 0.12.3", "rand", "serde", "serde_bytes", @@ -290,7 +290,7 @@ dependencies = [ "serde_dhall", "serde_json", "serde_test", - "sha2 0.10.7", + "sha2 0.10.8", "stacker", "test-generator", "thiserror", @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.4" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" +checksum = "824956d0dca8334758a5b7f7e50518d66ea319330cbceedcf76905c2f6ab30e3" dependencies = [ "clap_builder", "clap_derive", @@ -378,9 +378,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.4" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" +checksum = "122ec64120a49b4563ccaedcbea7818d069ed8e9aa6d829b82d8a4128936b2ab" dependencies = [ "anstream", "anstyle", @@ -506,16 +506,6 @@ dependencies = [ "itertools 0.10.5", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -613,7 +603,7 @@ version = "0.3.5" dependencies = [ "anyhow", "candid", - "clap 4.4.4", + "clap 4.4.5", "hex", "pretty-hex", "rand", @@ -740,9 +730,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fixedbitset" @@ -884,9 +874,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e" dependencies = [ "equivalent", "hashbrown 0.14.0", @@ -1108,16 +1098,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.3", - "libc", -] - [[package]] name = "num_enum" version = "0.6.1" @@ -1200,9 +1180,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" dependencies = [ "memchr", "thiserror", @@ -1233,9 +1213,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bee7be22ce7918f641a33f08e3f43388c7656772244e2bbb2477f44cc9021a" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" dependencies = [ "pest", "pest_generator", @@ -1243,9 +1223,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1511785c5e98d79a05e8a6bc34b4ac2168a0e3e92161862030ad84daa223141" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" dependencies = [ "pest", "pest_meta", @@ -1256,13 +1236,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -1272,7 +1252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.0", + "indexmap 2.0.1", ] [[package]] @@ -1344,13 +1324,13 @@ dependencies = [ [[package]] name = "pretty" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563c9d701c3a31dfffaaf9ce23507ba09cbe0b9125ba176d15e629b0235e9acc" +checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" dependencies = [ "arrayvec", "typed-arena", - "unicode-segmentation", + "unicode-width", ] [[package]] @@ -1446,9 +1426,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -1456,14 +1436,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -1663,9 +1641,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -1828,18 +1806,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2 1.0.67", "quote 1.0.33", @@ -1892,7 +1870,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.1", "toml_datetime", "winnow", ] diff --git a/Cargo.toml b/Cargo.toml index 4e7620d3..352d28c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,5 @@ members = [ "rust/candid_derive", "tools/didc", ] +resolver = "2" + diff --git a/Changelog.md b/Changelog.md index 8fc58128..a7b4fbf7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,19 @@ # Changelog +## 2023-09-27 + +### Rust 0.9.8 + +* Implement `CandidType` for `std::cmp::Reverse`. +* Rust codegen: add `pub` for struct fields. +* Fix `merge_init_types` and `instantiate_candid` when the main actor refers to a variable. + +### Candid UI + +* Draw flamegraph for canister upgrade +* Upstream fix from `merge_init_types` + ## Rust 0.9.7 * Add `utils::merge_init_args` to parse and merge `candid:args` metadata, and add the same endpoint in Candid UI. diff --git a/rust/candid/Cargo.toml b/rust/candid/Cargo.toml index ee403fab..41947962 100644 --- a/rust/candid/Cargo.toml +++ b/rust/candid/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "candid" -version = "0.9.7" +version = "0.9.8" edition = "2021" 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/bindings/rust.rs b/rust/candid/src/bindings/rust.rs index 2e347bc4..fe399dbb 100644 --- a/rust/candid/src/bindings/rust.rs +++ b/rust/candid/src/bindings/rust.rs @@ -81,18 +81,6 @@ fn ident_(id: &str, case: Option) -> (RcDoc, bool) { fn ident(id: &str, case: Option) -> RcDoc { ident_(id, case).0 } -fn field_name(id: &str, case: Option) -> RcDoc { - let (doc, is_rename) = ident_(id, case); - if is_rename { - str("#[serde(rename=\"") - .append(id.escape_debug().to_string()) - .append("\")]") - .append(RcDoc::line()) - .append(doc) - } else { - doc - } -} fn pp_ty<'a>(ty: &'a Type, recs: &RecPoints) -> RcDoc<'a> { use TypeInner::*; @@ -127,7 +115,7 @@ fn pp_ty<'a>(ty: &'a Type, recs: &RecPoints) -> RcDoc<'a> { // It's a bit tricky to use `deserialize_with = "serde_bytes"`. It's not working for `type t = blob` Vec(ref t) if matches!(t.as_ref(), Nat8) => str("serde_bytes::ByteBuf"), Vec(ref t) => str("Vec").append(enclose("<", pp_ty(t, recs), ">")), - Record(ref fs) => pp_record_fields(fs, recs), + Record(ref fs) => pp_record_fields(fs, recs, ""), Variant(_) => unreachable!(), // not possible after rewriting Func(_) => unreachable!(), // not possible after rewriting Service(_) => unreachable!(), // not possible after rewriting @@ -136,34 +124,62 @@ fn pp_ty<'a>(ty: &'a Type, recs: &RecPoints) -> RcDoc<'a> { } } -fn pp_label(id: &SharedLabel, is_variant: bool) -> RcDoc { +fn pp_label<'a>(id: &'a SharedLabel, is_variant: bool, vis: &'a str) -> RcDoc<'a> { + let vis = if vis.is_empty() { + RcDoc::nil() + } else { + kwd(vis) + }; match &**id { - Label::Named(str) => field_name(str, if is_variant { Some(Case::Pascal) } else { None }), - Label::Id(n) | Label::Unnamed(n) => str("_").append(RcDoc::as_string(n)).append("_"), + Label::Named(id) => { + let case = if is_variant { Some(Case::Pascal) } else { None }; + let (doc, is_rename) = ident_(id, case); + if is_rename { + str("#[serde(rename=\"") + .append(id.escape_debug().to_string()) + .append("\")]") + .append(RcDoc::line()) + .append(vis) + .append(doc) + } else { + vis.append(doc) + } + } + Label::Id(n) | Label::Unnamed(n) => vis.append("_").append(RcDoc::as_string(n)).append("_"), } } -fn pp_record_field<'a>(field: &'a Field, recs: &RecPoints) -> RcDoc<'a> { - pp_label(&field.id, false) +fn pp_record_field<'a>(field: &'a Field, recs: &RecPoints, vis: &'a str) -> RcDoc<'a> { + pp_label(&field.id, false, vis) .append(kwd(":")) .append(pp_ty(&field.ty, recs)) } -fn pp_record_fields<'a>(fs: &'a [Field], recs: &RecPoints) -> RcDoc<'a> { +fn pp_record_fields<'a>(fs: &'a [Field], recs: &RecPoints, vis: &'a str) -> RcDoc<'a> { if is_tuple(fs) { - let tuple = RcDoc::concat(fs.iter().map(|f| pp_ty(&f.ty, recs).append(","))); + let vis = if vis.is_empty() { + RcDoc::nil() + } else { + kwd(vis) + }; + let tuple = RcDoc::concat( + fs.iter() + .map(|f| vis.clone().append(pp_ty(&f.ty, recs)).append(",")), + ); enclose("(", tuple, ")") } else { - let fields = concat(fs.iter().map(|f| pp_record_field(f, recs)), ","); + let fields = concat(fs.iter().map(|f| pp_record_field(f, recs, vis)), ","); enclose_space("{", fields, "}") } } fn pp_variant_field<'a>(field: &'a Field, recs: &RecPoints) -> RcDoc<'a> { match field.ty.as_ref() { - TypeInner::Null => pp_label(&field.id, true), - TypeInner::Record(fs) => pp_label(&field.id, true).append(pp_record_fields(fs, recs)), - _ => pp_label(&field.id, true).append(enclose("(", pp_ty(&field.ty, recs), ")")), + TypeInner::Null => pp_label(&field.id, true, ""), + TypeInner::Record(fs) => { + pp_label(&field.id, true, "").append(pp_record_fields(fs, recs, "")) + } + _ => pp_label(&field.id, true, "").append(enclose("(", pp_ty(&field.ty, recs), ")")), } } @@ -199,7 +215,7 @@ fn pp_defs<'a>( .append(vis) .append("struct ") .append(name) - .append(pp_record_fields(fs, recs)) + .append(pp_record_fields(fs, recs, "pub")) .append(separator) .append(RcDoc::hardline()) } diff --git a/rust/candid/src/types/impls.rs b/rust/candid/src/types/impls.rs index 8f7acd80..3caf1077 100644 --- a/rust/candid/src/types/impls.rs +++ b/rust/candid/src/types/impls.rs @@ -299,6 +299,21 @@ where } } +impl CandidType for std::cmp::Reverse +where + T: CandidType, +{ + fn _ty() -> Type { + T::ty() + } + fn idl_serialize(&self, serializer: S) -> Result<(), S::Error> + where + S: Serializer, + { + self.0.idl_serialize(serializer) + } +} + impl<'a, T> CandidType for &'a T where T: ?Sized + CandidType, diff --git a/rust/candid/src/utils.rs b/rust/candid/src/utils.rs index c251be65..64bee0a2 100644 --- a/rust/candid/src/utils.rs +++ b/rust/candid/src/utils.rs @@ -88,6 +88,7 @@ pub fn instantiate_candid(candid: CandidSource) -> Result<(Vec, (TypeEnv, use crate::types::TypeInner; let (env, serv) = candid.load()?; let serv = serv.ok_or_else(|| Error::msg("the Candid interface has no main service type"))?; + let serv = env.trace_type(&serv)?; Ok(match serv.as_ref() { TypeInner::Class(args, ty) => (args.clone(), (env, ty.clone())), TypeInner::Service(_) => (vec![], (env, serv)), @@ -105,6 +106,7 @@ pub fn merge_init_args(candid: &str, init: &str) -> Result<(TypeEnv, Type)> { let candid = CandidSource::Text(candid); let (env, serv) = candid.load()?; let serv = serv.ok_or_else(|| Error::msg("the Candid interface has no main service type"))?; + let serv = env.trace_type(&serv)?; match serv.as_ref() { TypeInner::Class(_, _) => Ok((env, serv)), TypeInner::Service(_) => { diff --git a/rust/candid/tests/assets/ok/escape.rs b/rust/candid/tests/assets/ok/escape.rs index 597a887c..6325fdc9 100644 --- a/rust/candid/tests/assets/ok/escape.rs +++ b/rust/candid/tests/assets/ok/escape.rs @@ -7,13 +7,13 @@ use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct T { #[serde(rename="\"")] - _34_: candid::Nat, + pub _34_: candid::Nat, #[serde(rename="\'")] - _39_: candid::Nat, + pub _39_: candid::Nat, #[serde(rename="\"\'")] - _7621_: candid::Nat, + pub _7621_: candid::Nat, #[serde(rename="\\\n\'\"")] - _1020746185_: candid::Nat, + pub _1020746185_: candid::Nat, } pub struct Service(pub Principal); diff --git a/rust/candid/tests/assets/ok/example.rs b/rust/candid/tests/assets/ok/example.rs index e054f72f..a3ef4ca7 100644 --- a/rust/candid/tests/assets/ok/example.rs +++ b/rust/candid/tests/assets/ok/example.rs @@ -5,33 +5,33 @@ use candid::{self, CandidType, Deserialize, Principal, Encode, Decode}; use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] -pub struct Node { head: candid::Nat, tail: Box } +pub struct Node { pub head: candid::Nat, pub tail: Box } #[derive(CandidType, Deserialize)] pub struct List(Option); pub type MyType = Principal; #[derive(CandidType, Deserialize)] -pub struct ListInner { head: candid::Int, tail: Box } +pub struct ListInner { pub head: candid::Int, pub tail: Box } #[derive(CandidType, Deserialize)] pub struct List(Option); #[derive(CandidType, Deserialize)] -pub struct Nested3 { _0_: candid::Nat, _42_: candid::Nat, _43_: u8 } +pub struct Nested3 { pub _0_: candid::Nat, pub _42_: candid::Nat, pub _43_: u8 } #[derive(CandidType, Deserialize)] pub enum Nested41 { _42_, A, B, C } #[derive(CandidType, Deserialize)] pub struct Nested { - _0_: candid::Nat, - _1_: candid::Nat, - _2_: (candid::Nat,candid::Int,), - _3_: Nested3, - _40_: candid::Nat, - _41_: Nested41, - _42_: candid::Nat, + pub _0_: candid::Nat, + pub _1_: candid::Nat, + pub _2_: (candid::Nat,candid::Int,), + pub _3_: Nested3, + pub _40_: candid::Nat, + pub _41_: Nested41, + pub _42_: candid::Nat, } candid::define_service!(pub BrokerFindRet : { @@ -48,12 +48,12 @@ pub enum HArg1 { A(candid::Nat), B(Option) } pub struct HRet42 {} #[derive(CandidType, Deserialize)] -pub struct HRet { _42_: HRet42, id: candid::Nat } +pub struct HRet { pub _42_: HRet42, pub id: candid::Nat } candid::define_function!(pub FArg1 : (i32) -> (i64)); candid::define_function!(pub F : (List, FArg1) -> (Option)); #[derive(CandidType, Deserialize)] -pub struct B (candid::Int,candid::Nat,); +pub struct B (pub candid::Int,pub candid::Nat,); #[derive(CandidType, Deserialize)] pub enum A { #[serde(rename="a")] A, #[serde(rename="b")] B(B) } diff --git a/rust/candid/tests/assets/ok/fieldnat.rs b/rust/candid/tests/assets/ok/fieldnat.rs index af18e604..a42fec7c 100644 --- a/rust/candid/tests/assets/ok/fieldnat.rs +++ b/rust/candid/tests/assets/ok/fieldnat.rs @@ -5,31 +5,35 @@ use candid::{self, CandidType, Deserialize, Principal, Encode, Decode}; use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] -pub struct BarArg { #[serde(rename="2")] _50_: candid::Int } +pub struct BarArg { #[serde(rename="2")] pub _50_: candid::Int } #[derive(CandidType, Deserialize)] pub enum BarRet { #[serde(rename="e20")] E20, #[serde(rename="e30")] E30 } #[derive(CandidType, Deserialize)] -pub struct BazArg { _2_: candid::Int, #[serde(rename="2")] _50_: candid::Nat } +pub struct BazArg { + pub _2_: candid::Int, + #[serde(rename="2")] + pub _50_: candid::Nat, +} #[derive(CandidType, Deserialize)] pub struct BazRet {} #[derive(CandidType, Deserialize)] -pub struct Tuple (String,String,); +pub struct Tuple (pub String,pub String,); #[derive(CandidType, Deserialize)] -pub struct NonTuple { _1_: String, _2_: String } +pub struct NonTuple { pub _1_: String, pub _2_: String } #[derive(CandidType, Deserialize)] pub enum BibRet { _0_(candid::Int) } #[derive(CandidType, Deserialize)] -pub struct FooArg { _2_: candid::Int } +pub struct FooArg { pub _2_: candid::Int } #[derive(CandidType, Deserialize)] -pub struct FooRet { _2_: candid::Int, _2: candid::Int } +pub struct FooRet { pub _2_: candid::Int, pub _2: candid::Int } pub struct Service(pub Principal); impl Service { diff --git a/rust/candid/tests/assets/ok/keyword.rs b/rust/candid/tests/assets/ok/keyword.rs index fc4e9bc5..0010e120 100644 --- a/rust/candid/tests/assets/ok/keyword.rs +++ b/rust/candid/tests/assets/ok/keyword.rs @@ -8,20 +8,20 @@ use ic_cdk::api::call::CallResult as Result; pub struct O(Option>); #[derive(CandidType, Deserialize)] -pub struct FieldArg { test: u16, _1291438163_: u8 } +pub struct FieldArg { pub test: u16, pub _1291438163_: u8 } #[derive(CandidType, Deserialize)] pub struct FieldRet {} #[derive(CandidType, Deserialize)] pub struct FieldnatArg { - _2_: candid::Int, + pub _2_: candid::Int, #[serde(rename="2")] - _50_: candid::Nat, + pub _50_: candid::Nat, } #[derive(CandidType, Deserialize)] -pub struct Node { head: candid::Nat, tail: Box } +pub struct Node { pub head: candid::Nat, pub tail: Box } #[derive(CandidType, Deserialize)] pub struct List(Option); @@ -36,7 +36,7 @@ pub enum If { candid::define_function!(pub StreamInnerNext : () -> (Stream) query); #[derive(CandidType, Deserialize)] -pub struct StreamInner { head: candid::Nat, next: StreamInnerNext } +pub struct StreamInner { pub head: candid::Nat, pub next: StreamInnerNext } #[derive(CandidType, Deserialize)] pub struct Stream(Option); diff --git a/rust/candid/tests/assets/ok/management.rs b/rust/candid/tests/assets/ok/management.rs index 48d784ca..a74b2a2b 100644 --- a/rust/candid/tests/assets/ok/management.rs +++ b/rust/candid/tests/assets/ok/management.rs @@ -15,14 +15,14 @@ pub enum BitcoinNetwork { pub type BitcoinAddress = String; #[derive(CandidType, Deserialize)] pub struct GetBalanceRequest { - network: BitcoinNetwork, - address: BitcoinAddress, - min_confirmations: Option, + pub network: BitcoinNetwork, + pub address: BitcoinAddress, + pub min_confirmations: Option, } pub type Satoshi = u64; #[derive(CandidType, Deserialize)] -pub struct GetCurrentFeePercentilesRequest { network: BitcoinNetwork } +pub struct GetCurrentFeePercentilesRequest { pub network: BitcoinNetwork } pub type MillisatoshiPerByte = u64; #[derive(CandidType, Deserialize)] @@ -35,35 +35,35 @@ pub enum GetUtxosRequestFilterInner { #[derive(CandidType, Deserialize)] pub struct GetUtxosRequest { - network: BitcoinNetwork, - filter: Option, - address: BitcoinAddress, + pub network: BitcoinNetwork, + pub filter: Option, + pub address: BitcoinAddress, } pub type BlockHash = serde_bytes::ByteBuf; #[derive(CandidType, Deserialize)] -pub struct Outpoint { txid: serde_bytes::ByteBuf, vout: u32 } +pub struct Outpoint { pub txid: serde_bytes::ByteBuf, pub vout: u32 } #[derive(CandidType, Deserialize)] -pub struct Utxo { height: u32, value: Satoshi, outpoint: Outpoint } +pub struct Utxo { pub height: u32, pub value: Satoshi, pub outpoint: Outpoint } #[derive(CandidType, Deserialize)] pub struct GetUtxosResponse { - next_page: Option, - tip_height: u32, - tip_block_hash: BlockHash, - utxos: Vec, + pub next_page: Option, + pub tip_height: u32, + pub tip_block_hash: BlockHash, + pub utxos: Vec, } #[derive(CandidType, Deserialize)] pub struct SendTransactionRequest { - transaction: serde_bytes::ByteBuf, - network: BitcoinNetwork, + pub transaction: serde_bytes::ByteBuf, + pub network: BitcoinNetwork, } pub type CanisterId = Principal; #[derive(CandidType, Deserialize)] -pub struct CanisterStatusArg { canister_id: CanisterId } +pub struct CanisterStatusArg { pub canister_id: CanisterId } #[derive(CandidType, Deserialize)] pub enum CanisterStatusRetStatus { @@ -77,59 +77,59 @@ pub enum CanisterStatusRetStatus { #[derive(CandidType, Deserialize)] pub struct DefiniteCanisterSettings { - freezing_threshold: candid::Nat, - controllers: Vec, - memory_allocation: candid::Nat, - compute_allocation: candid::Nat, + pub freezing_threshold: candid::Nat, + pub controllers: Vec, + pub memory_allocation: candid::Nat, + pub compute_allocation: candid::Nat, } #[derive(CandidType, Deserialize)] pub struct CanisterStatusRet { - status: CanisterStatusRetStatus, - memory_size: candid::Nat, - cycles: candid::Nat, - settings: DefiniteCanisterSettings, - idle_cycles_burned_per_day: candid::Nat, - module_hash: Option, + pub status: CanisterStatusRetStatus, + pub memory_size: candid::Nat, + pub cycles: candid::Nat, + pub settings: DefiniteCanisterSettings, + pub idle_cycles_burned_per_day: candid::Nat, + pub module_hash: Option, } #[derive(CandidType, Deserialize)] pub struct CanisterSettings { - freezing_threshold: Option, - controllers: Option>, - memory_allocation: Option, - compute_allocation: Option, + pub freezing_threshold: Option, + pub controllers: Option>, + pub memory_allocation: Option, + pub compute_allocation: Option, } #[derive(CandidType, Deserialize)] -pub struct CreateCanisterArg { settings: Option } +pub struct CreateCanisterArg { pub settings: Option } #[derive(CandidType, Deserialize)] -pub struct CreateCanisterRet { canister_id: CanisterId } +pub struct CreateCanisterRet { pub canister_id: CanisterId } #[derive(CandidType, Deserialize)] -pub struct DeleteCanisterArg { canister_id: CanisterId } +pub struct DeleteCanisterArg { pub canister_id: CanisterId } #[derive(CandidType, Deserialize)] -pub struct DepositCyclesArg { canister_id: CanisterId } +pub struct DepositCyclesArg { pub canister_id: CanisterId } #[derive(CandidType, Deserialize)] pub enum EcdsaCurve { #[serde(rename="secp256k1")] Secp256K1 } #[derive(CandidType, Deserialize)] -pub struct EcdsaPublicKeyArgKeyId { name: String, curve: EcdsaCurve } +pub struct EcdsaPublicKeyArgKeyId { pub name: String, pub curve: EcdsaCurve } #[derive(CandidType, Deserialize)] pub struct EcdsaPublicKeyArg { - key_id: EcdsaPublicKeyArgKeyId, - canister_id: Option, - derivation_path: Vec, + pub key_id: EcdsaPublicKeyArgKeyId, + pub canister_id: Option, + pub derivation_path: Vec, } #[derive(CandidType, Deserialize)] pub struct EcdsaPublicKeyRet { - public_key: serde_bytes::ByteBuf, - chain_code: serde_bytes::ByteBuf, + pub public_key: serde_bytes::ByteBuf, + pub chain_code: serde_bytes::ByteBuf, } #[derive(CandidType, Deserialize)] @@ -143,19 +143,19 @@ pub enum HttpRequestArgMethod { } #[derive(CandidType, Deserialize)] -pub struct HttpHeader { value: String, name: String } +pub struct HttpHeader { pub value: String, pub name: String } #[derive(CandidType, Deserialize)] pub struct HttpResponse { - status: candid::Nat, - body: serde_bytes::ByteBuf, - headers: Vec, + pub status: candid::Nat, + pub body: serde_bytes::ByteBuf, + pub headers: Vec, } #[derive(CandidType, Deserialize)] pub struct HttpRequestArgTransformInnerFunctionArg { - context: serde_bytes::ByteBuf, - response: HttpResponse, + pub context: serde_bytes::ByteBuf, + pub response: HttpResponse, } candid::define_function!(pub HttpRequestArgTransformInnerFunction : ( @@ -163,18 +163,18 @@ candid::define_function!(pub HttpRequestArgTransformInnerFunction : ( ) -> (HttpResponse) query); #[derive(CandidType, Deserialize)] pub struct HttpRequestArgTransformInner { - function: HttpRequestArgTransformInnerFunction, - context: serde_bytes::ByteBuf, + pub function: HttpRequestArgTransformInnerFunction, + pub context: serde_bytes::ByteBuf, } #[derive(CandidType, Deserialize)] pub struct HttpRequestArg { - url: String, - method: HttpRequestArgMethod, - max_response_bytes: Option, - body: Option, - transform: Option, - headers: Vec, + pub url: String, + pub method: HttpRequestArgMethod, + pub max_response_bytes: Option, + pub body: Option, + pub transform: Option, + pub headers: Vec, } pub type WasmModule = serde_bytes::ByteBuf; @@ -190,54 +190,56 @@ pub enum InstallCodeArgMode { #[derive(CandidType, Deserialize)] pub struct InstallCodeArg { - arg: serde_bytes::ByteBuf, - wasm_module: WasmModule, - mode: InstallCodeArgMode, - canister_id: CanisterId, + pub arg: serde_bytes::ByteBuf, + pub wasm_module: WasmModule, + pub mode: InstallCodeArgMode, + pub canister_id: CanisterId, } #[derive(CandidType, Deserialize)] pub struct ProvisionalCreateCanisterWithCyclesArg { - settings: Option, - specified_id: Option, - amount: Option, + pub settings: Option, + pub specified_id: Option, + pub amount: Option, } #[derive(CandidType, Deserialize)] -pub struct ProvisionalCreateCanisterWithCyclesRet { canister_id: CanisterId } +pub struct ProvisionalCreateCanisterWithCyclesRet { + pub canister_id: CanisterId, +} #[derive(CandidType, Deserialize)] pub struct ProvisionalTopUpCanisterArg { - canister_id: CanisterId, - amount: candid::Nat, + pub canister_id: CanisterId, + pub amount: candid::Nat, } #[derive(CandidType, Deserialize)] -pub struct SignWithEcdsaArgKeyId { name: String, curve: EcdsaCurve } +pub struct SignWithEcdsaArgKeyId { pub name: String, pub curve: EcdsaCurve } #[derive(CandidType, Deserialize)] pub struct SignWithEcdsaArg { - key_id: SignWithEcdsaArgKeyId, - derivation_path: Vec, - message_hash: serde_bytes::ByteBuf, + pub key_id: SignWithEcdsaArgKeyId, + pub derivation_path: Vec, + pub message_hash: serde_bytes::ByteBuf, } #[derive(CandidType, Deserialize)] -pub struct SignWithEcdsaRet { signature: serde_bytes::ByteBuf } +pub struct SignWithEcdsaRet { pub signature: serde_bytes::ByteBuf } #[derive(CandidType, Deserialize)] -pub struct StartCanisterArg { canister_id: CanisterId } +pub struct StartCanisterArg { pub canister_id: CanisterId } #[derive(CandidType, Deserialize)] -pub struct StopCanisterArg { canister_id: CanisterId } +pub struct StopCanisterArg { pub canister_id: CanisterId } #[derive(CandidType, Deserialize)] -pub struct UninstallCodeArg { canister_id: CanisterId } +pub struct UninstallCodeArg { pub canister_id: CanisterId } #[derive(CandidType, Deserialize)] pub struct UpdateSettingsArg { - canister_id: Principal, - settings: CanisterSettings, + pub canister_id: Principal, + pub settings: CanisterSettings, } pub struct Service<'a>(pub Principal, pub &'a ic_agent::Agent); diff --git a/rust/candid/tests/assets/ok/recursion.rs b/rust/candid/tests/assets/ok/recursion.rs index f773d7f7..25095093 100644 --- a/rust/candid/tests/assets/ok/recursion.rs +++ b/rust/candid/tests/assets/ok/recursion.rs @@ -6,7 +6,7 @@ use ic_cdk::api::call::CallResult as Result; candid::define_function!(pub T : (S) -> ()); #[derive(CandidType, Deserialize)] -pub struct Node { head: candid::Nat, tail: Box } +pub struct Node { pub head: candid::Nat, pub tail: Box } #[derive(CandidType, Deserialize)] pub struct List(Option); @@ -25,7 +25,7 @@ pub enum Tree { candid::define_function!(pub StreamInnerNext : () -> (Stream) query); #[derive(CandidType, Deserialize)] -pub struct StreamInner { head: candid::Nat, next: StreamInnerNext } +pub struct StreamInner { pub head: candid::Nat, pub next: StreamInnerNext } #[derive(CandidType, Deserialize)] pub struct Stream(Option); diff --git a/rust/candid/tests/assets/ok/unicode.did b/rust/candid/tests/assets/ok/unicode.did index ba83564b..fddd5d0c 100644 --- a/rust/candid/tests/assets/ok/unicode.did +++ b/rust/candid/tests/assets/ok/unicode.did @@ -1,4 +1,9 @@ -type A = record { "\u{e000}" : nat; "📦🍦" : nat; "字段名" : nat; "字 段 名2" : nat }; +type A = record { + "\u{e000}" : nat; + "📦🍦" : nat; + "字段名" : nat; + "字 段 名2" : nat; +}; type B = variant { ""; "空的"; " 空的 "; "1⃣️2⃣️3⃣️" }; service : { "" : (nat) -> (nat); diff --git a/rust/candid/tests/assets/ok/unicode.rs b/rust/candid/tests/assets/ok/unicode.rs index 73dd059d..6bb2c33f 100644 --- a/rust/candid/tests/assets/ok/unicode.rs +++ b/rust/candid/tests/assets/ok/unicode.rs @@ -7,13 +7,13 @@ use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct A { #[serde(rename="\u{e000}")] - _11864174_: candid::Nat, + pub _11864174_: candid::Nat, #[serde(rename="📦🍦")] - _1832283146_: candid::Nat, + pub _1832283146_: candid::Nat, #[serde(rename="字段名")] - _2119362116_: candid::Nat, + pub _2119362116_: candid::Nat, #[serde(rename="字 段 名2")] - _3133479156_: candid::Nat, + pub _3133479156_: candid::Nat, } #[derive(CandidType, Deserialize)] diff --git a/tools/ui/Cargo.lock b/tools/ui/Cargo.lock index 47229acc..e57fe4b4 100644 --- a/tools/ui/Cargo.lock +++ b/tools/ui/Cargo.lock @@ -111,7 +111,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "candid" -version = "0.9.6" +version = "0.9.7" dependencies = [ "anyhow", "binread", diff --git a/tools/ui/Cargo.toml b/tools/ui/Cargo.toml index 4eb9f146..417b2764 100644 --- a/tools/ui/Cargo.toml +++ b/tools/ui/Cargo.toml @@ -2,6 +2,7 @@ members = [ "src/didjs", ] +resolver = "2" [profile.release] lto = true diff --git a/tools/ui/src/candid.ts b/tools/ui/src/candid.ts index 42b578d0..b57b55e0 100644 --- a/tools/ui/src/candid.ts +++ b/tools/ui/src/candid.ts @@ -148,8 +148,8 @@ export async function getProfiling(canisterId: Principal): Promise) { //console.log(input); - if (!input) { - return []; + if (!input || input.length == 0) { + return undefined; } const stack: Array<[number, bigint, any[]]> = [[0,BigInt(0),[]]]; let prev_id = undefined; @@ -239,6 +239,7 @@ export function render(id: Principal, canister: ActorSubclass, profiling: bigint if (typeof profiling !== 'undefined') { log(`Wasm instructions executed ${profiling} instrs.`); profiler = async () => { return await getProfiling(id) }; + renderFlameGraph(profiler); } const sortedMethods = Actor.interfaceOf(canister)._fields.sort(([a], [b]) => (a > b ? 1 : -1)); for (const [name, func] of sortedMethods) { diff --git a/tools/ui/src/didjs/lib.rs b/tools/ui/src/didjs/lib.rs index 62c5d657..9b920928 100644 --- a/tools/ui/src/didjs/lib.rs +++ b/tools/ui/src/didjs/lib.rs @@ -45,6 +45,7 @@ fn binding(prog: String, lang: String) -> Option { "mo" => bindings::motoko::compile(&env, &actor), "installed_did" => { let actor = actor.and_then(|t: Type| { + let t = env.trace_type(&t).ok()?; if let TypeInner::Class(_, ty) = t.as_ref() { Some(ty.clone()) } else { @@ -75,7 +76,7 @@ fn subtype(new: String, old: String) -> Result<(), String> { let old_actor = check_prog(&mut old_env, &old).unwrap().unwrap(); let mut gamma = std::collections::HashSet::new(); let old_actor = new_env.merge_type(old_env, old_actor); - subtype::subtype(&mut gamma, &new_env, &new_actor, &old_actor).or_else(|e| Err(e.to_string())) + subtype::subtype(&mut gamma, &new_env, &new_actor, &old_actor).map_err(|e| e.to_string()) } fn retrieve(path: &str) -> Option<&'static [u8]> {