casper_client/cli/
json_args.rs

1//! `CLType` and `CLValue` parsing and validation from "json args" syntax.
2
3mod error;
4pub mod help;
5
6use std::str::FromStr;
7
8use serde::{Deserialize, Serialize};
9use serde_json::{json, Value};
10
11use casper_types::{
12    bytesrepr::{ToBytes, OPTION_NONE_TAG, OPTION_SOME_TAG, RESULT_ERR_TAG, RESULT_OK_TAG},
13    AsymmetricType, CLType, CLValue, Key, NamedArg, PublicKey, URef, U128, U256, U512,
14};
15
16use crate::cli::CliError;
17pub use error::{Error, ErrorDetails};
18
19/// Represents a JSON argument with a name, type, and value.
20#[derive(Clone, Serialize, Deserialize, Debug)]
21pub struct JsonArg {
22    name: String,
23    #[serde(rename = "type")]
24    cl_type: CLType,
25    value: Value,
26}
27
28impl TryFrom<JsonArg> for NamedArg {
29    type Error = CliError;
30
31    fn try_from(json_arg: JsonArg) -> Result<Self, Self::Error> {
32        let mut bytes = vec![];
33        write_json_to_bytesrepr(&json_arg.cl_type, &json_arg.value, &mut bytes).map_err(
34            |details| {
35                Error::new(
36                    json_arg.name.clone(),
37                    json_arg.cl_type.clone(),
38                    json_arg.value,
39                    details,
40                )
41            },
42        )?;
43        Ok(NamedArg::new(
44            json_arg.name,
45            CLValue::from_components(json_arg.cl_type, bytes),
46        ))
47    }
48}
49
50fn write_json_to_bytesrepr(
51    cl_type: &CLType,
52    json_value: &Value,
53    output: &mut Vec<u8>,
54) -> Result<(), ErrorDetails> {
55    match (cl_type, json_value) {
56        (&CLType::Bool, Value::Bool(bool)) => bool.write_bytes(output)?,
57        (&CLType::I32, Value::Number(number)) => {
58            let value = number
59                .as_i64()
60                .and_then(|value| i32::try_from(value).ok())
61                .ok_or(ErrorDetails::CannotParseToI32)?;
62            value.write_bytes(output)?;
63        }
64        (&CLType::I64, Value::Number(number)) => {
65            let value = number.as_i64().ok_or(ErrorDetails::CannotParseToI64)?;
66            value.write_bytes(output)?;
67        }
68        (&CLType::U8, Value::Number(number)) => {
69            let value = number
70                .as_u64()
71                .and_then(|value| u8::try_from(value).ok())
72                .ok_or(ErrorDetails::CannotParseToU8)?;
73            value.write_bytes(output)?;
74        }
75        (&CLType::U32, Value::Number(number)) => {
76            let value = number
77                .as_u64()
78                .and_then(|value| u32::try_from(value).ok())
79                .ok_or(ErrorDetails::CannotParseToU32)?;
80            value.write_bytes(output)?;
81        }
82        (&CLType::U64, Value::Number(number)) => {
83            let value = number.as_u64().ok_or(ErrorDetails::CannotParseToU64)?;
84            value.write_bytes(output)?;
85        }
86        (&CLType::U128, Value::String(string)) => {
87            let value = U128::from_dec_str(string)?;
88            value.write_bytes(output)?;
89        }
90        (&CLType::U128, Value::Number(number)) => {
91            let value = number.as_u64().ok_or(ErrorDetails::CannotParseToU64)?;
92            U128::from(value).write_bytes(output)?;
93        }
94        (&CLType::U256, Value::String(string)) => {
95            let value = U256::from_dec_str(string)?;
96            value.write_bytes(output)?;
97        }
98        (&CLType::U256, Value::Number(number)) => {
99            let value = number.as_u64().ok_or(ErrorDetails::CannotParseToU64)?;
100            U256::from(value).write_bytes(output)?;
101        }
102        (&CLType::U512, Value::String(string)) => {
103            let value = U512::from_dec_str(string)?;
104            value.write_bytes(output)?;
105        }
106        (&CLType::U512, Value::Number(number)) => {
107            let value = number.as_u64().ok_or(ErrorDetails::CannotParseToU64)?;
108            U512::from(value).write_bytes(output)?;
109        }
110        (&CLType::Unit, Value::Null) => (),
111        (&CLType::String, Value::String(string)) => string.write_bytes(output)?,
112        (&CLType::Key, Value::String(string)) => {
113            let value = Key::from_formatted_str(string)?;
114            value.write_bytes(output)?;
115        }
116        (&CLType::Key, Value::Object(map)) => {
117            // This is an alternative JSON representation of a `Key`, e.g. if calling
118            // `serde_json::to_string()` on a `Key` enum.
119            if map.len() != 1 {
120                return Err(ErrorDetails::KeyObjectHasInvalidNumberOfFields);
121            }
122            let (mapped_variant, mapped_string) = match map.iter().next() {
123                Some((k, Value::String(v))) => (k, v),
124                _ => return Err(ErrorDetails::KeyObjectHasInvalidFieldType),
125            };
126            let value = Key::from_formatted_str(mapped_string)?;
127            // Return an error if the variant name doesn't match the parsed `Key` variant.
128            match value {
129                Key::Account(_) if mapped_variant == "Account" => {}
130                Key::Hash(_) if mapped_variant == "Hash" => {}
131                Key::URef(_) if mapped_variant == "URef" => {}
132                Key::Transfer(_) if mapped_variant == "Transfer" => {}
133                Key::DeployInfo(_) if mapped_variant == "DeployInfo" => {}
134                Key::EraInfo(_) if mapped_variant == "EraInfo" => {}
135                Key::Balance(_) if mapped_variant == "Balance" => {}
136                Key::Bid(_) if mapped_variant == "Bid" => {}
137                Key::Withdraw(_) if mapped_variant == "Withdraw" => {}
138                Key::Dictionary(_) if mapped_variant == "Dictionary" => {}
139                Key::SystemEntityRegistry if mapped_variant == "SystemEntityRegistry" => {}
140                Key::Unbond(_) if mapped_variant == "Unbond" => {}
141                Key::ChainspecRegistry if mapped_variant == "ChainspecRegistry" => {}
142                _ => return Err(ErrorDetails::KeyObjectHasInvalidVariant),
143            }
144            value.write_bytes(output)?;
145        }
146        (&CLType::URef, Value::String(string)) => {
147            let value = URef::from_formatted_str(string)?;
148            value.write_bytes(output)?;
149        }
150        (&CLType::PublicKey, Value::String(string)) => {
151            let value = PublicKey::from_hex(string)?;
152            value.write_bytes(output)?;
153        }
154        (CLType::Option(ref _inner_cl_type), Value::Null) => {
155            output.push(OPTION_NONE_TAG);
156        }
157        (CLType::Option(ref inner_cl_type), _) => {
158            output.push(OPTION_SOME_TAG);
159            write_json_to_bytesrepr(inner_cl_type, json_value, output)?;
160        }
161        (CLType::List(ref inner_cl_type), Value::Array(vec)) => {
162            (vec.len() as u32).write_bytes(output)?;
163            for item in vec {
164                write_json_to_bytesrepr(inner_cl_type, item, output)?;
165            }
166        }
167        (CLType::List(ref inner_cl_type), Value::String(string)) => {
168            // Support passing a `Vec<u8>` as a hex-encoded string.
169            if **inner_cl_type != CLType::U8 {
170                return Err(ErrorDetails::IncompatibleType);
171            }
172            let mut value = base16::decode(string)?;
173            (value.len() as u32).write_bytes(output)?;
174            output.append(&mut value);
175        }
176        (&CLType::ByteArray(expected_length), Value::String(string)) => {
177            let mut value = base16::decode(string)?;
178            let actual_length = value.len() as u32;
179            if actual_length != expected_length {
180                return Err(ErrorDetails::ByteArrayLengthMismatch {
181                    expected_length,
182                    actual_length,
183                });
184            }
185            output.append(&mut value);
186        }
187        (&CLType::ByteArray(expected_length), Value::Array(array)) => {
188            // While we generally output byte arrays in JSON as hex-encoded strings, we want to
189            // support explicit JSON arrays too.
190            let actual_length = array.len() as u32;
191            if actual_length != expected_length {
192                return Err(ErrorDetails::ByteArrayLengthMismatch {
193                    expected_length,
194                    actual_length,
195                });
196            }
197            for value in array {
198                let byte = value
199                    .as_u64()
200                    .and_then(|value| u8::try_from(value).ok())
201                    .ok_or(ErrorDetails::CannotParseToU8)?;
202                output.push(byte);
203            }
204        }
205        (CLType::Result { ref ok, ref err }, Value::Object(map)) => {
206            if map.len() != 1 {
207                return Err(ErrorDetails::ResultObjectHasInvalidNumberOfFields);
208            }
209            match map.iter().next() {
210                Some((key, value)) if key.eq_ignore_ascii_case("ok") => {
211                    output.push(RESULT_OK_TAG);
212                    write_json_to_bytesrepr(ok, value, output)?;
213                }
214                Some((key, value)) if key.eq_ignore_ascii_case("err") => {
215                    output.push(RESULT_ERR_TAG);
216                    write_json_to_bytesrepr(err, value, output)?;
217                }
218                _ => return Err(ErrorDetails::ResultObjectHasInvalidVariant),
219            }
220        }
221        (
222            CLType::Map {
223                key: ref key_type,
224                value: ref value_type,
225            },
226            Value::Object(map),
227        ) => {
228            // While we generally output maps in JSON as arrays of objects of the form
229            // '[{"key":KEY-1,"value":VALUE-1},{"key":KEY-2,"value":VALUE-2}]', we want to
230            // support maps which can be converted to JSON via `serde_json::to_string`.  Such maps
231            // are limited to ones where the key type is a String or Number, and will take the form
232            // '{"KEY-1":VALUE-1,"KEY-2":VALUE-2}'.
233            match **key_type {
234                CLType::I32
235                | CLType::I64
236                | CLType::U8
237                | CLType::U32
238                | CLType::U64
239                | CLType::U128
240                | CLType::U256
241                | CLType::U512
242                | CLType::String => (),
243                _ => return Err(ErrorDetails::MapTypeNotValidAsObject(*key_type.clone())),
244            };
245            (map.len() as u32).write_bytes(output)?;
246            for (key_as_str, value) in map {
247                let key = match **key_type {
248                    CLType::I32 => json!(i32::from_str(key_as_str)?),
249                    CLType::I64 => json!(i64::from_str(key_as_str)?),
250                    CLType::U8 => json!(u8::from_str(key_as_str)?),
251                    CLType::U32 => json!(u32::from_str(key_as_str)?),
252                    CLType::U64 => json!(u64::from_str(key_as_str)?),
253                    CLType::U128 => json!(U128::from_dec_str(key_as_str)?),
254                    CLType::U256 => json!(U256::from_dec_str(key_as_str)?),
255                    CLType::U512 => json!(U512::from_dec_str(key_as_str)?),
256                    CLType::String => json!(key_as_str),
257                    _ => return Err(ErrorDetails::MapTypeNotValidAsObject(*key_type.clone())),
258                };
259                write_json_to_bytesrepr(key_type, &key, output)?;
260                write_json_to_bytesrepr(value_type, value, output)?;
261            }
262        }
263        (
264            CLType::Map {
265                key: ref key_type,
266                value: ref value_type,
267            },
268            Value::Array(array),
269        ) => {
270            (array.len() as u32).write_bytes(output)?;
271            for item in array {
272                let map = if let Some(map) = item.as_object() {
273                    map
274                } else {
275                    return Err(ErrorDetails::MapArrayHasInvalidEntryType);
276                };
277                if map.len() != 2 {
278                    return Err(ErrorDetails::MapEntryObjectHasInvalidNumberOfFields);
279                }
280                let key = map
281                    .get("key")
282                    .ok_or(ErrorDetails::MapEntryObjectMissingKeyField)?;
283                write_json_to_bytesrepr(key_type, key, output)?;
284                let value = map
285                    .get("value")
286                    .ok_or(ErrorDetails::MapEntryObjectMissingValueField)?;
287                write_json_to_bytesrepr(value_type, value, output)?;
288            }
289        }
290        (CLType::Tuple1(ref inner_cl_types), Value::Array(vec)) => {
291            if vec.len() != inner_cl_types.len() {
292                return Err(ErrorDetails::TupleEntryCountMismatch {
293                    expected: inner_cl_types.len(),
294                    actual: vec.len(),
295                });
296            }
297            write_json_to_bytesrepr(&inner_cl_types[0], &vec[0], output)?;
298        }
299        (CLType::Tuple2(ref inner_cl_types), Value::Array(vec)) => {
300            if vec.len() != inner_cl_types.len() {
301                return Err(ErrorDetails::TupleEntryCountMismatch {
302                    expected: inner_cl_types.len(),
303                    actual: vec.len(),
304                });
305            }
306            write_json_to_bytesrepr(&inner_cl_types[0], &vec[0], output)?;
307            write_json_to_bytesrepr(&inner_cl_types[1], &vec[1], output)?;
308        }
309        (CLType::Tuple3(ref inner_cl_types), Value::Array(vec)) => {
310            if vec.len() != inner_cl_types.len() {
311                return Err(ErrorDetails::TupleEntryCountMismatch {
312                    expected: inner_cl_types.len(),
313                    actual: vec.len(),
314                });
315            }
316            write_json_to_bytesrepr(&inner_cl_types[0], &vec[0], output)?;
317            write_json_to_bytesrepr(&inner_cl_types[1], &vec[1], output)?;
318            write_json_to_bytesrepr(&inner_cl_types[2], &vec[2], output)?;
319        }
320        _ => return Err(ErrorDetails::IncompatibleType),
321    };
322    Ok(())
323}
324
325#[cfg(test)]
326mod tests {
327    use std::collections::BTreeMap;
328
329    use casper_types::{account::AccountHash, bytesrepr::Bytes, AccessRights, CLTyped, EraId};
330
331    use super::*;
332
333    const ARRAY: [u8; 32] = [17; 32];
334
335    fn arg_name() -> String {
336        "arg name".to_string()
337    }
338
339    fn create_input(type_str: &str, value_str: &str) -> String {
340        format!(
341            r#"{{"name":"{}","type":{},"value":{}}}"#,
342            arg_name(),
343            type_str,
344            value_str
345        )
346    }
347
348    fn should_parse<T: ToBytes + CLTyped + Serialize>(
349        type_str: &str,
350        value_str: &str,
351        expected: T,
352    ) {
353        let input = create_input(type_str, value_str);
354        let parsed: JsonArg = serde_json::from_str(&input).unwrap();
355        let named_arg = NamedArg::try_from(parsed)
356            .unwrap_or_else(|error| panic!("unexpected error: {}", error));
357        let expected = NamedArg::new(arg_name(), CLValue::from_t(expected).unwrap());
358        assert_eq!(named_arg, expected);
359    }
360
361    fn get_error(type_str: &str, value_str: &str) -> ErrorDetails {
362        let input = create_input(type_str, value_str);
363        let json_arg: JsonArg = serde_json::from_str(&input).unwrap();
364        let mut bytes = vec![];
365        write_json_to_bytesrepr(&json_arg.cl_type, &json_arg.value, &mut bytes).unwrap_err()
366    }
367
368    #[test]
369    fn should_parse_bool() {
370        const TYPE: &str = r#""Bool""#;
371        should_parse(TYPE, "true", true);
372        should_parse(TYPE, "false", false);
373    }
374
375    #[test]
376    fn should_parse_i32() {
377        const TYPE: &str = r#""I32""#;
378        should_parse(TYPE, "-2147483648", i32::MIN);
379        should_parse(TYPE, "-1", -1_i32);
380        should_parse(TYPE, "0", 0_i32);
381        should_parse(TYPE, "1", 1_i32);
382        should_parse(TYPE, "2147483647", i32::MAX);
383    }
384
385    #[test]
386    fn should_parse_i64() {
387        const TYPE: &str = r#""I64""#;
388        should_parse(TYPE, "-9223372036854775808", i64::MIN);
389        should_parse(TYPE, "-1", -1_i64);
390        should_parse(TYPE, "0", 0_i64);
391        should_parse(TYPE, "1", 1_i64);
392        should_parse(TYPE, "9223372036854775807", i64::MAX);
393    }
394
395    #[test]
396    fn should_parse_u8() {
397        const TYPE: &str = r#""U8""#;
398        should_parse(TYPE, "0", 0_u8);
399        should_parse(TYPE, "255", u8::MAX);
400    }
401
402    #[test]
403    fn should_parse_u32() {
404        const TYPE: &str = r#""U32""#;
405        should_parse(TYPE, "0", 0_u32);
406        should_parse(TYPE, "4294967295", u32::MAX);
407    }
408
409    #[test]
410    fn should_parse_u64() {
411        const TYPE: &str = r#""U64""#;
412        should_parse(TYPE, "0", 0_u64);
413        should_parse(TYPE, "18446744073709551615", u64::MAX);
414    }
415
416    #[test]
417    fn should_parse_u128() {
418        const TYPE: &str = r#""U128""#;
419        // From string.
420        should_parse(TYPE, r#""0""#, U128::zero());
421        should_parse(
422            TYPE,
423            r#""340282366920938463463374607431768211455""#,
424            U128::MAX,
425        );
426
427        // From number.
428        should_parse(TYPE, "0", U128::zero());
429        should_parse(TYPE, "18446744073709551615", U128::from(u64::MAX));
430    }
431
432    #[test]
433    fn should_parse_u256() {
434        const TYPE: &str = r#""U256""#;
435        // From string.
436        should_parse(TYPE, r#""0""#, U256::zero());
437        should_parse(
438            TYPE,
439            r#""115792089237316195423570985008687907853269984665640564039457584007913129639935""#,
440            U256::MAX,
441        );
442
443        // From number.
444        should_parse(TYPE, "0", U256::zero());
445        should_parse(TYPE, "18446744073709551615", U256::from(u64::MAX));
446    }
447
448    #[test]
449    fn should_parse_u512() {
450        const TYPE: &str = r#""U512""#;
451        // From string.
452        should_parse(TYPE, r#""0""#, U512::zero());
453        should_parse(
454            TYPE,
455            r#""13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095""#,
456            U512::MAX,
457        );
458
459        // From number.
460        should_parse(TYPE, "0", U512::zero());
461        should_parse(TYPE, "18446744073709551615", U512::from(u64::MAX));
462    }
463
464    #[test]
465    fn should_parse_unit() {
466        const TYPE: &str = r#""Unit""#;
467        should_parse(TYPE, "null", ());
468    }
469
470    #[test]
471    fn should_parse_string() {
472        const TYPE: &str = r#""String""#;
473        should_parse(TYPE, r#""""#, String::new());
474        should_parse(TYPE, r#""some text""#, "some text".to_string());
475    }
476
477    #[test]
478    fn should_parse_key() {
479        const TYPE: &str = r#""Key""#;
480        const UREF: URef = URef::new(ARRAY, AccessRights::NONE);
481
482        // From formatted string.
483        should_parse(
484            TYPE,
485            r#""account-hash-1111111111111111111111111111111111111111111111111111111111111111""#,
486            Key::Account(AccountHash::new(ARRAY)),
487        );
488        // From JSON Object.
489        should_parse(
490            TYPE,
491            r#"{"Account":"account-hash-1111111111111111111111111111111111111111111111111111111111111111"}"#,
492            Key::Account(AccountHash::new(ARRAY)),
493        );
494
495        // From formatted string.
496        should_parse(
497            TYPE,
498            r#""hash-1111111111111111111111111111111111111111111111111111111111111111""#,
499            Key::Hash(ARRAY),
500        );
501        // From JSON Object.
502        should_parse(
503            TYPE,
504            r#"{"Hash":"hash-1111111111111111111111111111111111111111111111111111111111111111"}"#,
505            Key::Hash(ARRAY),
506        );
507
508        // From formatted string.
509        should_parse(
510            TYPE,
511            r#""uref-1111111111111111111111111111111111111111111111111111111111111111-000""#,
512            Key::URef(UREF),
513        );
514        // From JSON Object.
515        should_parse(
516            TYPE,
517            r#"{"URef":"uref-1111111111111111111111111111111111111111111111111111111111111111-000"}"#,
518            Key::URef(UREF),
519        );
520
521        // From formatted string.
522        should_parse(TYPE, r#""era-1""#, Key::EraInfo(EraId::new(1)));
523        // From JSON Object.
524        should_parse(TYPE, r#"{"EraInfo":"era-1"}"#, Key::EraInfo(EraId::new(1)));
525    }
526
527    #[test]
528    fn should_parse_uref() {
529        const TYPE: &str = r#""URef""#;
530        should_parse(
531            TYPE,
532            r#""uref-1111111111111111111111111111111111111111111111111111111111111111-007""#,
533            URef::new(ARRAY, AccessRights::all()),
534        );
535    }
536
537    #[test]
538    fn should_parse_public_key() {
539        const TYPE: &str = r#""PublicKey""#;
540        should_parse(
541            TYPE,
542            r#""011111111111111111111111111111111111111111111111111111111111111111""#,
543            PublicKey::ed25519_from_bytes(ARRAY).unwrap(),
544        );
545    }
546
547    #[test]
548    fn should_parse_option() {
549        const SIMPLE_TYPE: &str = r#"{"Option":"U64"}"#;
550        should_parse(SIMPLE_TYPE, "999", Some(999_u64));
551        should_parse::<Option<u64>>(SIMPLE_TYPE, "null", None);
552
553        const COMPLEX_TYPE: &str = r#"{"Option":{"Tuple2":["Bool","U8"]}}"#;
554        should_parse(COMPLEX_TYPE, "[true,1]", Some((true, 1_u8)));
555        should_parse::<Option<(bool, u8)>>(COMPLEX_TYPE, "null", None);
556    }
557
558    #[test]
559    fn should_parse_list() {
560        const SIMPLE_TYPE: &str = r#"{"List":"U64"}"#;
561        should_parse(SIMPLE_TYPE, "[1,2,3]", vec![1_u64, 2, 3]);
562        should_parse(SIMPLE_TYPE, "[]", Vec::<u64>::new());
563
564        const COMPLEX_TYPE: &str = r#"{"List":{"Option":{"Tuple2":["Bool","U8"]}}}"#;
565        should_parse(
566            COMPLEX_TYPE,
567            "[[true,1],null,[false,2]]",
568            vec![Some((true, 1_u8)), None, Some((false, 2))],
569        );
570        should_parse(COMPLEX_TYPE, "[]", Vec::<Option<(bool, u8)>>::new());
571
572        // For List of U8 only, we can parse from a JSON String.
573        const BYTE_LIST_TYPE: &str = r#"{"List":"U8"}"#;
574        should_parse(
575            BYTE_LIST_TYPE,
576            r#""0102ff""#,
577            Bytes::from(vec![1_u8, 2, 255]),
578        );
579        should_parse(BYTE_LIST_TYPE, r#""""#, Bytes::from(vec![]));
580    }
581
582    #[test]
583    fn should_parse_byte_array() {
584        const BYTE_ARRAY_3_TYPE: &str = r#"{"ByteArray":3}"#;
585        const BYTE_ARRAY_3: [u8; 3] = [1, 20, 255];
586        // From hex-encoded string.
587        should_parse(BYTE_ARRAY_3_TYPE, r#""0114ff""#, BYTE_ARRAY_3);
588        // From array.
589        should_parse(BYTE_ARRAY_3_TYPE, "[1,20,255]", BYTE_ARRAY_3);
590
591        const BYTE_ARRAY_EMPTY_TYPE: &str = r#"{"ByteArray":0}"#;
592        // From hex-encoded string.
593        should_parse(BYTE_ARRAY_EMPTY_TYPE, r#""""#, []);
594        // From array.
595        should_parse(BYTE_ARRAY_EMPTY_TYPE, "[]", []);
596    }
597
598    #[test]
599    fn should_parse_result() {
600        const SIMPLE_TYPE: &str = r#"{"Result":{"ok":"Bool","err":"U8"}}"#;
601
602        should_parse::<Result<bool, u8>>(SIMPLE_TYPE, r#"{"Ok":true}"#, Ok(true));
603        should_parse::<Result<bool, u8>>(SIMPLE_TYPE, r#"{"ok":true}"#, Ok(true));
604        should_parse::<Result<bool, u8>>(SIMPLE_TYPE, r#"{"Err":1}"#, Err(1));
605        should_parse::<Result<bool, u8>>(SIMPLE_TYPE, r#"{"err":1}"#, Err(1));
606
607        const COMPLEX_TYPE: &str =
608            r#"{"Result":{"ok":{"Option":{"Tuple2":["Bool","U8"]}},"err":{"Option":"String"}}}"#;
609        should_parse::<Result<Option<(bool, u8)>, Option<String>>>(
610            COMPLEX_TYPE,
611            r#"{"Ok":[true,255]}"#,
612            Ok(Some((true, 255))),
613        );
614        should_parse::<Result<Option<(bool, u8)>, Option<String>>>(
615            COMPLEX_TYPE,
616            r#"{"Err":"failed"}"#,
617            Err(Some("failed".to_string())),
618        );
619    }
620
621    #[test]
622    fn should_parse_map() {
623        const SIMPLE_TYPE: &str = r#"{"Map":{"key":"U8","value":"Bool"}}"#;
624        let mut simple_map = BTreeMap::new();
625        simple_map.insert(1_u8, true);
626        simple_map.insert(2, false);
627
628        // From a JSON Object, only applicable where the key type is a Number or String.
629        let value_str = r#"{"1":true,"2":false}"#;
630        assert_eq!(value_str, serde_json::to_string(&simple_map).unwrap());
631        should_parse(SIMPLE_TYPE, value_str, simple_map.clone());
632        // From a JSON Array of Objects each with a 'key' and 'value' field.
633        should_parse(
634            SIMPLE_TYPE,
635            r#"[{"key":1,"value":true},{"key":2,"value":false}]"#,
636            simple_map,
637        );
638
639        // Empty map, from a JSON Object.
640        should_parse(SIMPLE_TYPE, "{}", BTreeMap::<u8, bool>::new());
641        // Empty map, from a JSON Array.
642        should_parse(SIMPLE_TYPE, "[]", BTreeMap::<u8, bool>::new());
643
644        const COMPLEX_TYPE: &str =
645            r#"{"Map":{"key":{"List":"U64"},"value":{"Map":{"key":"U8","value":"Bool"}}}}"#;
646        let list1 = vec![1_u64, 2, 3];
647        let mut simple_map1 = BTreeMap::new();
648        simple_map1.insert(10_u8, true);
649        simple_map1.insert(20, false);
650        let list2 = vec![4_u64, 5, 6];
651        let mut simple_map2 = BTreeMap::new();
652        simple_map2.insert(30_u8, true);
653        simple_map2.insert(40, false);
654        let mut complex_map = BTreeMap::new();
655        complex_map.insert(list1, simple_map1);
656        complex_map.insert(list2, simple_map2);
657        assert!(serde_json::to_string(&complex_map).is_err());
658
659        // Should fail from a JSON Object, as the key type is not a Number or String.
660        let input = create_input(COMPLEX_TYPE, value_str);
661        let parsed: JsonArg = serde_json::from_str(&input).unwrap();
662        assert!(NamedArg::try_from(parsed).is_err());
663
664        // From a JSON Array of Objects each with a 'key' and 'value' field.
665        should_parse(
666            COMPLEX_TYPE,
667            r#"[{"key":[1,2,3],"value":{"10":true,"20":false}},{"key":[4,5,6],"value":{"30":true,"40":false}}]"#,
668            complex_map,
669        );
670    }
671
672    #[test]
673    fn should_parse_tuple1() {
674        const SIMPLE_TYPE: &str = r#"{"Tuple1":["Bool"]}"#;
675        should_parse(SIMPLE_TYPE, "[true]", (true,));
676
677        const COMPLEX_TYPE: &str =
678            r#"{"Tuple1":[{"Result":{"ok":{"Option":"String"},"err":"I32"}}]}"#;
679        should_parse::<(Result<Option<String>, i32>,)>(
680            COMPLEX_TYPE,
681            r#"[{"Ok":null}]"#,
682            (Ok(None),),
683        );
684    }
685
686    #[test]
687    fn should_parse_tuple2() {
688        const SIMPLE_TYPE: &str = r#"{"Tuple2":["Bool","U8"]}"#;
689        should_parse(SIMPLE_TYPE, "[true,128]", (true, 128_u8));
690
691        const COMPLEX_TYPE1: &str =
692            r#"{"Tuple2":[{"Result":{"ok":{"Option":"String"},"err":"I32"}},"Bool"]}"#;
693        should_parse::<(Result<Option<String>, i32>, bool)>(
694            COMPLEX_TYPE1,
695            r#"[{"Ok":null},true]"#,
696            (Ok(None), true),
697        );
698
699        const COMPLEX_TYPE2: &str =
700            r#"{"Tuple2":["Bool",{"Result":{"ok":{"Option":"String"},"err":"I32"}}]}"#;
701        should_parse::<(bool, Result<Option<String>, i32>)>(
702            COMPLEX_TYPE2,
703            r#"[true,{"Ok":null}]"#,
704            (true, Ok(None)),
705        );
706    }
707
708    #[test]
709    fn should_parse_tuple3() {
710        const SIMPLE_TYPE: &str = r#"{"Tuple3":["Bool","U8","String"]}"#;
711        should_parse(
712            SIMPLE_TYPE,
713            r#"[true,128,"a"]"#,
714            (true, 128_u8, "a".to_string()),
715        );
716
717        const COMPLEX_TYPE1: &str =
718            r#"{"Tuple3":[{"Result":{"ok":{"Option":"String"},"err":"I32"}},"Bool","Unit"]}"#;
719        should_parse::<(Result<Option<String>, i32>, bool, ())>(
720            COMPLEX_TYPE1,
721            r#"[{"Ok":null},true,null]"#,
722            (Ok(None), true, ()),
723        );
724
725        const COMPLEX_TYPE2: &str =
726            r#"{"Tuple3":["Bool",{"Result":{"ok":{"Option":"String"},"err":"I32"}},"Unit"]}"#;
727        should_parse::<(bool, Result<Option<String>, i32>, ())>(
728            COMPLEX_TYPE2,
729            r#"[true,{"Ok":null},null]"#,
730            (true, Ok(None), ()),
731        );
732
733        const COMPLEX_TYPE3: &str =
734            r#"{"Tuple3":["Bool","Unit",{"Result":{"ok":{"Option":"String"},"err":"I32"}}]}"#;
735        should_parse::<(bool, (), Result<Option<String>, i32>)>(
736            COMPLEX_TYPE3,
737            r#"[true,null,{"Ok":null}]"#,
738            (true, (), Ok(None)),
739        );
740    }
741
742    #[test]
743    fn should_fail_to_parse_key_from_object() {
744        const TYPE: &str = r#""Key""#;
745
746        // Object has extra field.
747        let error = get_error(TYPE, r#"{"EraInfo":"era-1","extra field":null}"#);
748        assert!(
749            matches!(error, ErrorDetails::KeyObjectHasInvalidNumberOfFields),
750            "{}",
751            error
752        );
753
754        // Object has no fields.
755        let error = get_error(TYPE, "{}");
756        assert!(
757            matches!(error, ErrorDetails::KeyObjectHasInvalidNumberOfFields),
758            "{}",
759            error
760        );
761
762        // Object's key is not a valid `Key` variant.
763        let error = get_error(TYPE, r#"{"not a key variant":"era-1"}"#);
764        assert!(
765            matches!(error, ErrorDetails::KeyObjectHasInvalidVariant),
766            "{}",
767            error
768        );
769
770        // Object's value is an Array, not a `Key` as a formatted string.
771        let error = get_error(TYPE, r#"{"EraInfo":["era-1"]}"#);
772        assert!(
773            matches!(error, ErrorDetails::KeyObjectHasInvalidFieldType),
774            "{}",
775            error
776        );
777
778        // Object's value is a String, but not a validly-formatted Key string.
779        let error = get_error(TYPE, r#"{"EraInfo":"er-1"}"#);
780        assert!(
781            matches!(error, ErrorDetails::ParseKeyFromString(_)),
782            "{}",
783            error
784        );
785    }
786
787    #[test]
788    fn should_fail_to_parse_byte_array() {
789        const TYPE: &str = r#"{"ByteArray":3}"#;
790
791        // Parsing from String: wrong number of hex-decoded bytes.
792        let error = get_error(TYPE, r#""01020304""#);
793        assert!(
794            matches!(
795                error,
796                ErrorDetails::ByteArrayLengthMismatch {
797                    expected_length: 3,
798                    actual_length: 4
799                }
800            ),
801            "{}",
802            error
803        );
804
805        // Parsing from String: invalid hex-encoded string.
806        let error = get_error(TYPE, r#""01020g""#);
807        assert!(matches!(error, ErrorDetails::HexDecode(_)), "{}", error);
808
809        // Parsing from Array: wrong number of bytes.
810        let error = get_error(TYPE, "[1,2,3,4]");
811        assert!(
812            matches!(
813                error,
814                ErrorDetails::ByteArrayLengthMismatch {
815                    expected_length: 3,
816                    actual_length: 4
817                }
818            ),
819            "{}",
820            error
821        );
822
823        // Parsing from Array: invalid element.
824        let error = get_error(TYPE, "[1,2,256]");
825        assert!(matches!(error, ErrorDetails::CannotParseToU8), "{}", error);
826    }
827
828    #[test]
829    fn should_fail_to_parse_result() {
830        const TYPE: &str = r#"{"Result":{"ok":"Bool","err":"U8"}}"#;
831
832        // Object has extra field.
833        let error = get_error(TYPE, r#"{"Ok":true,"extra field":null}"#);
834        assert!(
835            matches!(error, ErrorDetails::ResultObjectHasInvalidNumberOfFields),
836            "{}",
837            error
838        );
839
840        // Object has no fields.
841        let error = get_error(TYPE, "{}");
842        assert!(
843            matches!(error, ErrorDetails::ResultObjectHasInvalidNumberOfFields),
844            "{}",
845            error
846        );
847
848        // Object's key is not a valid `Result` variant.
849        let error = get_error(TYPE, r#"{"A-ok":true}"#);
850        assert!(
851            matches!(error, ErrorDetails::ResultObjectHasInvalidVariant),
852            "{}",
853            error
854        );
855    }
856
857    #[test]
858    fn should_fail_to_parse_map_from_object() {
859        const INVALID_KEY_TYPE_FOR_OBJECT: &str = r#"{"Map":{"key":"Bool","value":"U8"}}"#;
860
861        // `CLType::Map<Bool, _>` cannot be represented as a JSON Object.
862        let error = get_error(INVALID_KEY_TYPE_FOR_OBJECT, r#"{"true":1}"#);
863        assert!(
864            matches!(error, ErrorDetails::MapTypeNotValidAsObject(CLType::Bool)),
865            "{}",
866            error
867        );
868
869        // As above, but with an empty Object should still fail.
870        let error = get_error(INVALID_KEY_TYPE_FOR_OBJECT, "{}");
871        assert!(
872            matches!(error, ErrorDetails::MapTypeNotValidAsObject(CLType::Bool)),
873            "{}",
874            error
875        );
876    }
877
878    #[test]
879    fn should_fail_to_parse_map_from_array() {
880        const TYPE: &str = r#"{"Map":{"key":"U8","value":"Bool"}}"#;
881
882        // From an Array, but with a non-Object entry.
883        let error = get_error(TYPE, r#"[{"key":1,"value":true},"non-object entry"]"#);
884        assert!(
885            matches!(error, ErrorDetails::MapArrayHasInvalidEntryType),
886            "{}",
887            error
888        );
889
890        // From an Array, but with an entry containing an extra field.
891        let error = get_error(
892            TYPE,
893            r#"[{"key":1,"value":true},{"key":2,"value":false,"extra field":null}]"#,
894        );
895        assert!(
896            matches!(error, ErrorDetails::MapEntryObjectHasInvalidNumberOfFields),
897            "{}",
898            error
899        );
900
901        // From an Array, but with an entry missing the "key" field.
902        let error = get_error(
903            TYPE,
904            r#"[{"key":1,"value":true},{"not key":2,"value":false}]"#,
905        );
906        assert!(
907            matches!(error, ErrorDetails::MapEntryObjectMissingKeyField),
908            "{}",
909            error
910        );
911
912        // From an Array, but with an entry missing the "key" field.
913        let error = get_error(
914            TYPE,
915            r#"[{"key":1,"value":true},{"key":2,"not value":false}]"#,
916        );
917        assert!(
918            matches!(error, ErrorDetails::MapEntryObjectMissingValueField),
919            "{}",
920            error
921        );
922    }
923
924    #[test]
925    fn should_fail_to_parse_tuple1() {
926        const TYPE: &str = r#"{"Tuple1":["Bool"]}"#;
927
928        // From an Array with too few entries.
929        let error = get_error(TYPE, "[]");
930        assert!(
931            matches!(
932                error,
933                ErrorDetails::TupleEntryCountMismatch {
934                    expected: 1,
935                    actual: 0
936                }
937            ),
938            "{}",
939            error
940        );
941
942        // From an Array with too many entries.
943        let error = get_error(TYPE, "[true,1]");
944        assert!(
945            matches!(
946                error,
947                ErrorDetails::TupleEntryCountMismatch {
948                    expected: 1,
949                    actual: 2
950                }
951            ),
952            "{}",
953            error
954        );
955    }
956
957    #[test]
958    fn should_fail_to_parse_tuple2() {
959        const TYPE: &str = r#"{"Tuple2":["Bool","U8"]}"#;
960
961        // From an Array with too few entries.
962        let error = get_error(TYPE, "[true]");
963        assert!(
964            matches!(
965                error,
966                ErrorDetails::TupleEntryCountMismatch {
967                    expected: 2,
968                    actual: 1
969                }
970            ),
971            "{}",
972            error
973        );
974
975        // From an Array with too many entries.
976        let error = get_error(TYPE, "[true,1,null]");
977        assert!(
978            matches!(
979                error,
980                ErrorDetails::TupleEntryCountMismatch {
981                    expected: 2,
982                    actual: 3
983                }
984            ),
985            "{}",
986            error
987        );
988    }
989
990    #[test]
991    fn should_fail_to_parse_tuple3() {
992        const TYPE: &str = r#"{"Tuple3":["Bool","U8","String"]}"#;
993
994        // From an Array with too few entries.
995        let error = get_error(TYPE, "[true,1]");
996        assert!(
997            matches!(
998                error,
999                ErrorDetails::TupleEntryCountMismatch {
1000                    expected: 3,
1001                    actual: 2
1002                }
1003            ),
1004            "{}",
1005            error
1006        );
1007
1008        // From an Array with too many entries.
1009        let error = get_error(TYPE, r#"[true,1,"a",null]"#);
1010        assert!(
1011            matches!(
1012                error,
1013                ErrorDetails::TupleEntryCountMismatch {
1014                    expected: 3,
1015                    actual: 4
1016                }
1017            ),
1018            "{}",
1019            error
1020        );
1021    }
1022}