Skip to content

Commit

Permalink
fix result struct binding
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyan-dfinity committed Jun 21, 2024
1 parent 223fe03 commit 9db7f38
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 16 deletions.
15 changes: 12 additions & 3 deletions rust/candid_parser/src/bindings/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ pub enum TypePath {
Vec,
RecordField(String),
VariantField(String),
ResultField(String),
Func(String),
Init,
}
Expand All @@ -728,7 +729,9 @@ fn path_to_var(path: &[TypePath]) -> String {
.iter()
.map(|node| match node {
TypePath::Id(id) => id.as_str(),
TypePath::RecordField(f) | TypePath::VariantField(f) => f.as_str(),
TypePath::RecordField(f) | TypePath::VariantField(f) | TypePath::ResultField(f) => {
f.as_str()
}
TypePath::Opt => "inner",
TypePath::Vec => "item",
TypePath::Func(id) => id.as_str(),
Expand Down Expand Up @@ -801,13 +804,19 @@ impl<'a> NominalState<'a> {
}
}
TypeInner::Variant(fs) => {
if matches!(path.last(), None | Some(TypePath::Id(_))) || as_result(fs).is_some() {
let is_result = as_result(fs).is_some();
if matches!(path.last(), None | Some(TypePath::Id(_))) || is_result {
let fs: Vec<_> = fs
.iter()
.map(|Field { id, ty }| {
let lab = id.to_string();
let old = self.state.push_state(&StateElem::Label(&lab));
path.push(TypePath::VariantField(id.to_string()));
if is_result {
// so that inner record gets a new name
path.push(TypePath::ResultField(id.to_string()));
} else {
path.push(TypePath::VariantField(id.to_string()));
}
let ty = self.nominalize(env, path, ty);
path.pop();
self.state.pop_state(old, StateElem::Label(&lab));
Expand Down
4 changes: 2 additions & 2 deletions rust/candid_parser/tests/assets/example.did
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ type broker = service {
(service {up:() -> (); current:() -> (nat32)});
};
type nested = record { nat; nat; record {nat;int;}; record { nat; 0x2a:nat; nat8; }; 42:nat; 40:nat; variant{ A; 0x2a; B; C }; };
type res = variant { Ok: nat; Err: empty };
type res = variant { Ok: record{int;nat}; Err: record{ error: text } };

service server : {
f1 : (list, test: blob, opt bool) -> () oneway;
g1 : (my_type, List, opt List, nested) -> (int, broker) query;
h : (vec opt text, variant { A: nat; B: opt text }, opt List) -> (record { id: nat; 0x2a: record {} });
i : f;
x : (a,b) -> (opt a, opt b, variant { Ok; Err: variant {a;b} }) composite_query;
x : (a,b) -> (opt a, opt b, variant { Ok: record { result: text }; Err: variant {a;b} }) composite_query;
}

6 changes: 3 additions & 3 deletions rust/candid_parser/tests/assets/ok/example.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export interface nested {
_42_ : bigint,
}
export interface node { 'head' : bigint, 'tail' : list }
export type res = { 'Ok' : bigint } |
{ 'Err' : never };
export type res = { 'Ok' : [bigint, bigint] } |
{ 'Err' : { 'error' : string } };
export interface s { 'f' : t, 'g' : ActorMethod<[list], [B, tree, stream]> }
export type stream = [] | [{ 'head' : bigint, 'next' : [Principal, string] }];
export type t = ActorMethod<[Principal], undefined>;
Expand Down Expand Up @@ -55,7 +55,7 @@ export interface _SERVICE {
[
[] | [a],
[] | [b],
{ 'Ok' : null } |
{ 'Ok' : { 'result' : string } } |
{ 'Err' : { 'a' : null } | { 'b' : null } },
]
>,
Expand Down
4 changes: 2 additions & 2 deletions rust/candid_parser/tests/assets/ok/example.did
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type nested = record {
42 : nat;
};
type node = record { head : nat; tail : list };
type res = variant { Ok : nat; Err : empty };
type res = variant { Ok : record { int; nat }; Err : record { error : text } };
type s = service { f : t; g : (list) -> (B, tree, stream) };
type stream = opt record { head : nat; next : func () -> (stream) query };
type t = func (s) -> ();
Expand All @@ -40,6 +40,6 @@ service : {
x : (a, b) -> (
opt a,
opt b,
variant { Ok; Err : variant { a; b } },
variant { Ok : record { result : text }; Err : variant { a; b } },
) composite_query;
}
7 changes: 5 additions & 2 deletions rust/candid_parser/tests/assets/ok/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ export const idlFactory = ({ IDL }) => {
[],
),
});
const res = IDL.Variant({ 'Ok' : IDL.Nat, 'Err' : IDL.Empty });
const res = IDL.Variant({
'Ok' : IDL.Tuple(IDL.Int, IDL.Nat),
'Err' : IDL.Record({ 'error' : IDL.Text }),
});
const f = IDL.Func(
[List, IDL.Func([IDL.Int32], [IDL.Int64], [])],
[IDL.Opt(List), res],
Expand Down Expand Up @@ -94,7 +97,7 @@ export const idlFactory = ({ IDL }) => {
IDL.Opt(a),
IDL.Opt(b),
IDL.Variant({
'Ok' : IDL.Null,
'Ok' : IDL.Record({ 'result' : IDL.Text }),
'Err' : IDL.Variant({ 'a' : IDL.Null, 'b' : IDL.Null }),
}),
],
Expand Down
4 changes: 2 additions & 2 deletions rust/candid_parser/tests/assets/ok/example.mo
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module {
_42_ : Nat;
};
public type node = { head : Nat; tail : list };
public type res = { #Ok : Nat; #Err : None };
public type res = { #Ok : (Int, Nat); #Err : { error : Text } };
public type s = actor { f : t; g : shared list -> async (B, tree, stream) };
public type stream = ?{ head : Nat; next : shared query () -> async stream };
public type t = shared s -> async ();
Expand All @@ -51,7 +51,7 @@ module {
x : shared composite query (a, b) -> async (
?a,
?b,
{ #Ok; #Err : { #a; #b } },
{ #Ok : { result : Text }; #Err : { #a; #b } },
);
}
}
8 changes: 6 additions & 2 deletions rust/candid_parser/tests/assets/ok/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,18 @@ pub(crate) struct HRet42 {}
#[derive(CandidType, Deserialize, Debug)]
pub(crate) struct HRet { pub(crate) _42_: HRet42, pub(crate) id: u128 }
candid::define_function!(pub(crate) FArg1 : (i32) -> (i64));
pub(crate) type Res = std::result::Result<u128, candid::Empty>;
#[derive(CandidType, Deserialize, Debug)]
pub(crate) struct ResErr { pub(crate) error: String }
pub(crate) type Res = std::result::Result<(candid::Int,u128,), ResErr>;
candid::define_function!(pub(crate) F : (MyList, FArg1) -> (
Option<MyList>,
Res,
));
#[derive(CandidType, Deserialize, Debug)]
pub(crate) enum A { #[serde(rename="a")] A, #[serde(rename="b")] B(B) }
#[derive(CandidType, Deserialize, Debug)]
pub(crate) struct XRet2Ok { pub(crate) result: String }
#[derive(CandidType, Deserialize, Debug)]
pub(crate) enum Error { #[serde(rename="a")] A, #[serde(rename="b")] B }

pub struct Service(pub Principal);
Expand All @@ -116,7 +120,7 @@ impl Service {
pub async fn i(&self, arg0: MyList, arg1: FArg1) -> Result<(Option<MyList>,Res,)> {
ic_cdk::call(self.0, "i", (arg0,arg1,)).await
}
pub async fn x(&self, arg0: A, arg1: B) -> Result<(Option<A>,Option<B>,std::result::Result<(), Error>,)> {
pub async fn x(&self, arg0: A, arg1: B) -> Result<(Option<A>,Option<B>,std::result::Result<XRet2Ok, Error>,)> {
ic_cdk::call(self.0, "x", (arg0,arg1,)).await
}
}
Expand Down

0 comments on commit 9db7f38

Please sign in to comment.