idl2json/
untyped_conversion.rs

1use crate::{
2    bytes::{convert_blob, convert_bytes},
3    Idl2JsonOptions,
4};
5use candid::types::value::IDLValue;
6use candid_parser::IDLArgs;
7use serde_json::value::Value as JsonValue;
8
9/// Converts a candid IDLValue to a serde JsonValue, without type information.
10///
11/// Note: The textual format in parentheses `(  )` represents IDLArgs containing
12/// zero or more IDLValues.  Unless you definitely wish to convert a single value
13/// you may wish to consider `idl_args2json` instead.
14pub fn idl2json(idl: &IDLValue, options: &Idl2JsonOptions) -> JsonValue {
15    match idl {
16        IDLValue::Blob(bytes) => convert_blob(bytes, options),
17        IDLValue::Bool(bool) => JsonValue::Bool(*bool),
18        IDLValue::Null => JsonValue::Null,
19        IDLValue::Text(s) => JsonValue::String(s.clone()),
20        IDLValue::Number(s) => JsonValue::String(s.clone()), // Unspecified number type
21        IDLValue::Float64(f) => serde_json::Number::from_f64(*f)
22            .map(JsonValue::Number)
23            .unwrap_or_else(|| JsonValue::String("NaN".to_string())),
24        IDLValue::Opt(value) => JsonValue::Array(vec![idl2json(value, options)]),
25        IDLValue::Vec(value) => convert_bytes(value, options)
26            .unwrap_or_else(|_| convert_non_bytes_array(value, options)),
27        IDLValue::Record(value) => JsonValue::Object(
28            value
29                .iter()
30                .map(|field| (format!("{}", field.id), idl2json(&field.val, options)))
31                .collect(),
32        ),
33        IDLValue::Variant(field) => JsonValue::Object(
34            vec![(format!("{}", field.0.id), idl2json(&field.0.val, options))]
35                .into_iter()
36                .collect(),
37        ),
38        IDLValue::Principal(p) => JsonValue::String(format!("{}", p)),
39        IDLValue::Service(p) => JsonValue::String(format!("{}", p)),
40        IDLValue::Func(p, c) => JsonValue::Object(
41            vec![
42                ("principal".to_string(), JsonValue::String(format!("{}", p))),
43                ("code".to_string(), JsonValue::String(c.to_string())),
44            ]
45            .into_iter()
46            .collect(),
47        ),
48        IDLValue::None => JsonValue::Array(vec![]),
49        IDLValue::Int(i) => JsonValue::String(format!("{}", i)),
50        IDLValue::Nat(i) => JsonValue::String(format!("{}", i)),
51        IDLValue::Nat8(i) => JsonValue::Number(serde_json::Number::from(*i)),
52        IDLValue::Nat16(i) => JsonValue::Number(serde_json::Number::from(*i)),
53        IDLValue::Nat32(i) => JsonValue::Number(serde_json::Number::from(*i)),
54        IDLValue::Nat64(i) => JsonValue::String(format!("{}", i)),
55        IDLValue::Int8(i) => JsonValue::Number(serde_json::Number::from(*i)),
56        IDLValue::Int16(i) => JsonValue::Number(serde_json::Number::from(*i)),
57        IDLValue::Int32(i) => JsonValue::Number(serde_json::Number::from(*i)),
58        IDLValue::Int64(i) => JsonValue::String(format!("{}", i)),
59        IDLValue::Float32(f) => serde_json::Number::from_f64(*f as f64)
60            .map(JsonValue::Number)
61            .unwrap_or_else(|| JsonValue::String("NaN".to_string())),
62        IDLValue::Reserved => JsonValue::String(idl.to_string()),
63    }
64}
65
66/// Conver
67pub(crate) fn convert_non_bytes_array(value: &[IDLValue], options: &Idl2JsonOptions) -> JsonValue {
68    JsonValue::Array(value.iter().map(|item| idl2json(item, options)).collect())
69}
70
71/// Converts a candid IDLArgs to a serde JsonValue, without type information.
72///
73/// Note: The textual format `( )` containing zero or more values represents an IDLArgs.
74pub fn idl_args2json(args: &IDLArgs, options: &Idl2JsonOptions) -> JsonValue {
75    convert_non_bytes_array(&args.args, options)
76}