daml_json/
value_decode.rs

1use crate::error::{DamlJsonCodecError, DamlJsonCodecResult};
2use crate::util::{AsSingleSliceExt, Required};
3use chrono::{offset, Date, DateTime, NaiveDate};
4use daml_grpc::data::value::{DamlEnum, DamlRecord, DamlRecordField, DamlValue, DamlVariant};
5use daml_grpc::data::DamlIdentifier;
6use daml_grpc::primitive_types::{DamlGenMap, DamlInt64, DamlNumeric, DamlTextMap};
7use daml_lf::element;
8use daml_lf::element::{DamlArchive, DamlData, DamlField, DamlType};
9use serde_json::{Map, Value};
10use std::convert::TryFrom;
11use std::str::FromStr;
12
13/// Decode a `DamlValue` from JSON.
14#[derive(Debug)]
15pub struct JsonValueDecoder<'a> {
16    arc: &'a DamlArchive<'a>,
17}
18
19impl<'a> JsonValueDecoder<'a> {
20    pub const fn new(arc: &'a DamlArchive<'a>) -> Self {
21        Self {
22            arc,
23        }
24    }
25
26    /// Recursively decode a GRPC `DamlValue` from a JSON `Value` for a given `DamlType`.
27    ///
28    /// See [`JsonValueEncoder`] and the
29    /// [Daml LF JSON Encoding specification](https://docs.daml.com/json-api/lf-value-specification.html) for details.
30    ///
31    /// [`JsonValueEncoder`]: crate::value_encode::JsonValueEncoder
32    pub fn decode(&self, json: &Value, ty: &DamlType<'_>) -> DamlJsonCodecResult<DamlValue> {
33        self.do_decode(json, ty, true)
34    }
35
36    /// Perform the decode.
37    ///
38    /// Here `top_level` refers to whether we are processing a value corresponding to the "top level" of a type or a
39    /// nested types.  This is required to support the "shortcut" decoding for optional fields.
40    fn do_decode(&self, json: &Value, ty: &DamlType<'_>, top_level: bool) -> DamlJsonCodecResult<DamlValue> {
41        match ty {
42            DamlType::Unit =>
43                if json.try_object()?.is_empty() {
44                    Ok(DamlValue::Unit)
45                } else {
46                    Err(DamlJsonCodecError::UnexpectedUnitData)
47                },
48            DamlType::Bool => Self::decode_bool(json),
49            DamlType::Int64 => Self::decode_int64(json),
50            DamlType::Text => Self::decode_text(json),
51            DamlType::Party => Self::decode_party(json),
52            DamlType::ContractId(_) => Self::decode_contract_id(json),
53            DamlType::Numeric(_) => Self::decode_numeric(json),
54            DamlType::Date => Self::decode_date(json),
55            DamlType::Timestamp => Self::decode_timestamp(json),
56            DamlType::List(tys) => Ok(DamlValue::List(
57                json.try_array()?
58                    .iter()
59                    .map(|item| self.do_decode(item, tys.as_single()?, true))
60                    .collect::<DamlJsonCodecResult<Vec<_>>>()?,
61            )),
62            DamlType::TextMap(tys) => Ok(DamlValue::Map(
63                json.try_object()?
64                    .iter()
65                    .map(|(k, v)| Ok((k.clone(), self.do_decode(v, tys.as_single()?, true)?)))
66                    .collect::<DamlJsonCodecResult<DamlTextMap<DamlValue>>>()?,
67            )),
68            DamlType::GenMap(tys) => {
69                let array = json.try_array()?;
70                let genmap = array
71                    .iter()
72                    .map(|item| match item.try_array()?.as_slice() {
73                        [k, v] => Ok((
74                            self.do_decode(k, tys.first().req()?, true)?,
75                            self.do_decode(v, tys.last().req()?, true)?,
76                        )),
77                        _ => Err(DamlJsonCodecError::UnexpectedGenMapTypes),
78                    })
79                    .collect::<DamlJsonCodecResult<DamlGenMap<DamlValue, DamlValue>>>()?;
80
81                // If the resulting GenMap containers fewer entries that the input array then we know that the input
82                // array must have contained duplicate keys and should therefore be rejected.
83                if array.len() == genmap.len() {
84                    Ok(DamlValue::GenMap(genmap))
85                } else {
86                    Err(DamlJsonCodecError::DuplicateGenMapKeys)
87                }
88            },
89            DamlType::TyCon(tycon) | DamlType::BoxedTyCon(tycon) => self.decode_data(
90                json,
91                self.arc
92                    .data_by_tycon(tycon)
93                    .ok_or_else(|| DamlJsonCodecError::DataNotFound(tycon.tycon().to_string()))?,
94            ),
95            DamlType::Optional(nested) => {
96                let single = nested.as_single()?;
97                if top_level {
98                    if json.is_null() {
99                        Ok(DamlValue::Optional(None))
100                    } else {
101                        Ok(DamlValue::Optional(Some(Box::new(self.do_decode(json, single, false)?))))
102                    }
103                } else {
104                    match json.try_array()?.as_slice() {
105                        [] => Ok(DamlValue::Optional(None)),
106                        [inner_json] =>
107                            Ok(DamlValue::Optional(Some(Box::new(self.do_decode(inner_json, single, false)?)))),
108                        _ => Err(DamlJsonCodecError::UnexpectedOptionalArrayLength),
109                    }
110                }
111            },
112            DamlType::Var(_)
113            | DamlType::Nat(_)
114            | DamlType::Arrow
115            | DamlType::Any
116            | DamlType::TypeRep
117            | DamlType::Bignumeric
118            | DamlType::RoundingMode
119            | DamlType::AnyException
120            | DamlType::Update
121            | DamlType::Scenario
122            | DamlType::Forall(_)
123            | DamlType::Struct(_)
124            | DamlType::Syn(_) => Err(DamlJsonCodecError::UnsupportedDamlType(ty.name().to_owned())),
125        }
126    }
127
128    fn decode_bool(json: &Value) -> DamlJsonCodecResult<DamlValue> {
129        Ok(DamlValue::Bool(json.try_bool()?))
130    }
131
132    fn decode_int64(json: &Value) -> DamlJsonCodecResult<DamlValue> {
133        match (json.as_i64(), json.as_str()) {
134            (Some(i64), None) => Ok(DamlValue::new_int64(i64)),
135            (None, Some(s)) => Ok(DamlValue::new_int64(DamlInt64::from_str(s)?)),
136            _ => Err(DamlJsonCodecError::UnexpectedJsonType(
137                "i64 or String".to_owned(),
138                Value::json_value_name(json).to_owned(),
139            )),
140        }
141    }
142
143    fn decode_numeric(json: &Value) -> DamlJsonCodecResult<DamlValue> {
144        match (json.as_f64(), json.as_str()) {
145            (Some(f64), None) => Ok(DamlValue::new_numeric(DamlNumeric::try_from(f64)?)),
146            (None, Some(s)) => Ok(DamlValue::new_numeric(DamlNumeric::from_str(s)?)),
147            _ => Err(DamlJsonCodecError::UnexpectedJsonType(
148                "f64 or String".to_owned(),
149                Value::json_value_name(json).to_owned(),
150            )),
151        }
152    }
153
154    fn decode_date(json: &Value) -> DamlJsonCodecResult<DamlValue> {
155        Ok(DamlValue::new_date(Date::from_utc(NaiveDate::parse_from_str(json.try_string()?, "%Y-%m-%d")?, offset::Utc)))
156    }
157
158    fn decode_timestamp(json: &Value) -> DamlJsonCodecResult<DamlValue> {
159        Ok(DamlValue::new_timestamp(DateTime::parse_from_rfc3339(json.try_string()?)?))
160    }
161
162    fn decode_text(json: &Value) -> DamlJsonCodecResult<DamlValue> {
163        Ok(DamlValue::new_text(json.try_string()?))
164    }
165
166    fn decode_party(json: &Value) -> DamlJsonCodecResult<DamlValue> {
167        Ok(DamlValue::new_party(json.try_string()?))
168    }
169
170    fn decode_contract_id(json: &Value) -> DamlJsonCodecResult<DamlValue> {
171        Ok(DamlValue::new_contract_id(json.try_string()?))
172    }
173
174    /// Decode a `DamlValue` from a JSON `Value` and `DamlData`.
175    fn decode_data(&self, json: &Value, data: &DamlData<'_>) -> DamlJsonCodecResult<DamlValue> {
176        match data {
177            DamlData::Template(template) => self.decode_record(json, template.fields()),
178            DamlData::Record(record) => self.decode_record(json, record.fields()),
179            DamlData::Variant(variant) => self.decode_variant(json, variant.fields()),
180            DamlData::Enum(data_enum) => Self::decode_enum(json, data_enum),
181        }
182    }
183
184    /// Decode a `DamlValue::Enum` from a JSON `Value` and `DamlEnum` fields.
185    fn decode_enum(json: &Value, data_enum: &element::DamlEnum<'_>) -> DamlJsonCodecResult<DamlValue> {
186        let constructor = json.try_string()?;
187        if data_enum.constructors().any(|c| c == constructor) {
188            Ok(DamlValue::Enum(DamlEnum::new(constructor, None::<DamlIdentifier>)))
189        } else {
190            Err(DamlJsonCodecError::UnknownEnumConstructor(constructor.to_owned()))
191        }
192    }
193
194    /// Decode a `DamlValue::Variant` from a JSON `Value` and `DamlVariant` fields.
195    fn decode_variant(&self, json: &Value, constructors: &[DamlField<'_>]) -> DamlJsonCodecResult<DamlValue> {
196        let object = json.try_object()?;
197        let tag = object.get("tag").req()?.try_string()?;
198        let value = object.get("value").req()?;
199        let constructor = constructors
200            .iter()
201            .find(|&field| field.name() == tag)
202            .ok_or_else(|| DamlJsonCodecError::UnknownVariantConstructor(tag.to_owned()))?;
203        Ok(DamlValue::Variant(DamlVariant::new(
204            constructor.name(),
205            Box::new(self.decode(value, constructor.ty())?),
206            None::<DamlIdentifier>,
207        )))
208    }
209
210    /// Decode a `DamlValue::Record` from a JSON `Value` and `DamlRecord` / `DamlTemplate` fields.
211    fn decode_record(&self, json: &Value, lf_fields: &[DamlField<'_>]) -> DamlJsonCodecResult<DamlValue> {
212        let fields = match (json.as_object(), json.as_array()) {
213            (Some(obj), None) => self.decode_record_object(obj, lf_fields)?,
214            (None, Some(arr)) => self.decode_record_array(arr, lf_fields)?,
215            _ =>
216                return Err(DamlJsonCodecError::UnexpectedJsonType(
217                    "Object or Array".to_owned(),
218                    Value::json_value_name(json).to_owned(),
219                )),
220        };
221        Ok(DamlValue::Record(DamlRecord::new(fields, None::<DamlIdentifier>)))
222    }
223
224    fn decode_record_object(
225        &self,
226        obj: &Map<String, Value>,
227        lf_fields: &[DamlField<'_>],
228    ) -> DamlJsonCodecResult<Vec<DamlRecordField>> {
229        lf_fields
230            .iter()
231            .map(|field| {
232                let field_name = field.name();
233                let field_ty = field.ty();
234                let field_json = obj.get(field_name);
235                match (field_ty, field_json) {
236                    (DamlType::Optional(_), None) =>
237                        Ok(DamlRecordField::new(Some(field_name), DamlValue::Optional(None))),
238                    (_, Some(json)) => Ok(DamlRecordField::new(Some(field_name), self.decode(json, field_ty)?)),
239                    (_, None) => Err(DamlJsonCodecError::MissingJsonRecordObjectField(field_name.to_owned())),
240                }
241            })
242            .collect::<DamlJsonCodecResult<Vec<DamlRecordField>>>()
243    }
244
245    fn decode_record_array(
246        &self,
247        arr: &[Value],
248        lf_fields: &[DamlField<'_>],
249    ) -> DamlJsonCodecResult<Vec<DamlRecordField>> {
250        lf_fields
251            .iter()
252            .enumerate()
253            .map(|(i, field)| {
254                let json = arr
255                    .get(i)
256                    .ok_or_else(|| DamlJsonCodecError::MissingJsonRecordArrayField(i, field.name().to_owned()))?;
257                Ok(DamlRecordField::new(Some(field.name()), self.decode(json, field.ty())?))
258            })
259            .collect::<DamlJsonCodecResult<Vec<DamlRecordField>>>()
260    }
261}
262
263/// Extension trait for JSON `Value` to add `try_xxx` methods.
264pub trait JsonTryAsExt {
265    fn try_null(&self) -> DamlJsonCodecResult<()>;
266    fn try_bool(&self) -> DamlJsonCodecResult<bool>;
267    fn try_int64(&self) -> DamlJsonCodecResult<i64>;
268    fn try_string(&self) -> DamlJsonCodecResult<&str>;
269    fn try_array(&self) -> DamlJsonCodecResult<&Vec<Value>>;
270    fn try_object(&self) -> DamlJsonCodecResult<&Map<String, Value>>;
271    fn make_unexpected_type_error(value: &Value, expected: &str) -> DamlJsonCodecError {
272        DamlJsonCodecError::UnexpectedJsonType(expected.to_owned(), Self::json_value_name(value).to_owned())
273    }
274    fn json_value_name(value: &Value) -> &str {
275        match value {
276            Value::Null => "Null",
277            Value::Bool(_) => "Bool",
278            Value::Number(_) => "Number",
279            Value::String(_) => "String",
280            Value::Array(_) => "Array",
281            Value::Object(_) => "Object",
282        }
283    }
284}
285
286impl JsonTryAsExt for Value {
287    fn try_null(&self) -> DamlJsonCodecResult<()> {
288        self.as_null().ok_or_else(|| Self::make_unexpected_type_error(self, "Null"))
289    }
290
291    fn try_bool(&self) -> DamlJsonCodecResult<bool> {
292        self.as_bool().ok_or_else(|| Self::make_unexpected_type_error(self, "Bool"))
293    }
294
295    fn try_int64(&self) -> DamlJsonCodecResult<i64> {
296        self.as_i64().ok_or_else(|| Self::make_unexpected_type_error(self, "Number(i64)"))
297    }
298
299    fn try_string(&self) -> DamlJsonCodecResult<&str> {
300        self.as_str().ok_or_else(|| Self::make_unexpected_type_error(self, "String"))
301    }
302
303    fn try_array(&self) -> DamlJsonCodecResult<&Vec<Value>> {
304        self.as_array().ok_or_else(|| Self::make_unexpected_type_error(self, "Array"))
305    }
306
307    fn try_object(&self) -> DamlJsonCodecResult<&Map<String, Value>> {
308        self.as_object().ok_or_else(|| Self::make_unexpected_type_error(self, "Object"))
309    }
310}
311
312#[cfg(test)]
313mod tests {
314    use super::{
315        DamlArchive, DamlEnum, DamlJsonCodecError, DamlJsonCodecResult, DamlType, DamlValue, JsonValueDecoder, Value,
316    };
317    use daml::macros::daml_value;
318    use daml_grpc::primitive_types::DamlTextMap;
319    use daml_lf::DarFile;
320    use maplit::hashmap;
321    use serde_json::json;
322
323    static TESTING_TYPES_DAR_PATH: &str = "../resources/testing_types_sandbox/TestingTypes-latest.dar";
324
325    /// `{}` -> `() : ()`
326    #[test]
327    fn test_unit() -> DamlJsonCodecResult<()> {
328        let json_value = json!({});
329        let ty = DamlType::Unit;
330        let expected = daml_value!();
331        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
332        assert_eq!(actual, expected);
333        Ok(())
334    }
335
336    /// `true` -> `True : bool`
337    #[test]
338    fn test_bool() -> DamlJsonCodecResult<()> {
339        let json_value = json!(true);
340        let ty = DamlType::Bool;
341        let expected = daml_value!(true);
342        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
343        assert_eq!(actual, expected);
344        Ok(())
345    }
346
347    /// `42` -> `42 : Int`
348    #[test]
349    fn test_int64() -> DamlJsonCodecResult<()> {
350        let json_value = json!(42);
351        let ty = DamlType::Int64;
352        let expected = daml_value!(42);
353        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
354        assert_eq!(actual, expected);
355        Ok(())
356    }
357
358    /// `-42` -> `-42 : Int`
359    #[test]
360    fn test_int64_neg() -> DamlJsonCodecResult<()> {
361        let json_value = json!(-42);
362        let ty = DamlType::Int64;
363        let expected = daml_value!(-42);
364        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
365        assert_eq!(actual, expected);
366        Ok(())
367    }
368
369    /// `"42"` -> `42 : Int`
370    #[test]
371    fn test_int64_string() -> DamlJsonCodecResult<()> {
372        let json_value = json!("42");
373        let ty = DamlType::Int64;
374        let expected = daml_value!(42);
375        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
376        assert_eq!(actual, expected);
377        Ok(())
378    }
379
380    /// `"-42"` -> `-42 : Int`
381    #[test]
382    fn test_int64_neg_string() -> DamlJsonCodecResult<()> {
383        let json_value = json!("-42");
384        let ty = DamlType::Int64;
385        let expected = daml_value!(-42);
386        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
387        assert_eq!(actual, expected);
388        Ok(())
389    }
390
391    /// `4.2` -> `4.2 : Int`
392    #[test]
393    fn test_int64_fails() {
394        let json_value = json!(4.2);
395        let ty = DamlType::Int64;
396        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
397        assert!(actual.is_err());
398    }
399
400    /// `1.0` -> `1.0 : Decimal`
401    #[test]
402    fn test_numeric_f64() -> DamlJsonCodecResult<()> {
403        let json_value = json!(1.0);
404        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
405        let expected = daml_value!(1.0);
406        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
407        assert_eq!(actual, expected);
408        Ok(())
409    }
410
411    /// `-1.0` -> `-1.0 : Decimal`
412    #[test]
413    fn test_numeric_f64_neg() -> DamlJsonCodecResult<()> {
414        let json_value = json!(-1.0);
415        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
416        let expected = daml_value!(-1.0);
417        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
418        assert_eq!(actual, expected);
419        Ok(())
420    }
421
422    /// `"1.23"` -> `1.23 : Decimal`
423    #[test]
424    fn test_numeric_string() -> DamlJsonCodecResult<()> {
425        let json_value = json!("1.23");
426        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
427        let expected = daml_value!(1.23);
428        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
429        assert_eq!(actual, expected);
430        Ok(())
431    }
432
433    /// `"-1.23"` -> `-1.23 : Decimal`
434    #[test]
435    fn test_numeric_string_neg() -> DamlJsonCodecResult<()> {
436        let json_value = json!("-1.23");
437        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
438        let expected = daml_value!(-1.23);
439        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
440        assert_eq!(actual, expected);
441        Ok(())
442    }
443
444    /// `0.30000000000000004` -> `0.3 : Decimal`
445    #[test]
446    #[allow(clippy::unreadable_literal)]
447    fn test_numeric_f64_round() -> DamlJsonCodecResult<()> {
448        let json_value = json!(0.30000000000000004);
449        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
450        let expected = daml_value!(0.3);
451        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
452        assert_eq!(actual, expected);
453        Ok(())
454    }
455
456    /// `2e3` -> `2000 : Decimal`
457    #[test]
458    fn test_numeric_f64_sci() -> DamlJsonCodecResult<()> {
459        let json_value = json!(2e3);
460        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
461        let expected = daml_value!(2000.0);
462        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
463        assert_eq!(actual, expected);
464        Ok(())
465    }
466
467    /// `-0` -> `0 : Decimal`
468    #[test]
469    fn test_numeric_f64_neg_zero() -> DamlJsonCodecResult<()> {
470        let json_value = json!(-0);
471        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
472        let expected = daml_value!(0.0);
473        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
474        assert_eq!(actual, expected);
475        Ok(())
476    }
477
478    /// `9999999999999999999999999999.9999999999` -> `9999999999999999999999999999.9999999999 : Decimal`
479    #[test]
480    #[allow(clippy::unreadable_literal)]
481    fn test_numeric_f64_large() -> DamlJsonCodecResult<()> {
482        let json_value = json!(9999999999999999999999999999.9999999999);
483        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
484        let expected = daml_value!(9999999999999999999999999999.9999999999);
485        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
486        assert_eq!(actual, expected);
487        Ok(())
488    }
489
490    /// `42` -> `42 : Decimal`
491    #[test]
492    fn test_numeric_f64_whole() -> DamlJsonCodecResult<()> {
493        let json_value = json!(42);
494        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
495        let expected = daml_value!(42.0);
496        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
497        assert_eq!(actual, expected);
498        Ok(())
499    }
500
501    /// `42` -> `42 : Decimal`
502    #[test]
503    fn test_numeric_string_whole() -> DamlJsonCodecResult<()> {
504        let json_value = json!("42");
505        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
506        let expected = daml_value!(42.0);
507        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
508        assert_eq!(actual, expected);
509        Ok(())
510    }
511
512    /// `"blah"` -> `n/a : Decimal`
513    #[test]
514    fn test_numeric_string_fails_garbage() {
515        let json_value = json!("blah");
516        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
517        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
518        assert!(actual.is_err());
519    }
520
521    /// `"  42  "` -> `n/a : Decimal`
522    #[test]
523    fn test_numeric_string_fails_whitespace() {
524        let json_value = json!("  42  ");
525        let ty = DamlType::Numeric(vec![DamlType::Nat(10)]);
526        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
527        assert!(actual.is_err());
528    }
529
530    /// `"test"` -> `"test" : Text`
531    #[test]
532    fn test_text() -> DamlJsonCodecResult<()> {
533        let json_value = json!("test");
534        let ty = DamlType::Text;
535        let expected = daml_value!("test");
536        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
537        assert_eq!(actual, expected);
538        Ok(())
539    }
540
541    /// `""` -> `"" : Text`
542    #[test]
543    fn test_text_empty() -> DamlJsonCodecResult<()> {
544        let json_value = json!("");
545        let ty = DamlType::Text;
546        let expected = daml_value!("");
547        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
548        assert_eq!(actual, expected);
549        Ok(())
550    }
551
552    /// `"2019-06-18"` -> `date 2019 Jun 18 : Text`
553    #[test]
554    fn test_date() -> DamlJsonCodecResult<()> {
555        let json_value = json!("2019-06-18");
556        let ty = DamlType::Date;
557        let expected = daml_value!("2019-06-18"::d);
558        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
559        assert_eq!(actual, expected);
560        Ok(())
561    }
562
563    /// `"9999-12-31"` -> `date 9999 Dec 31 : Text`
564    #[test]
565    fn test_date_min() -> DamlJsonCodecResult<()> {
566        let json_value = json!("9999-12-31");
567        let ty = DamlType::Date;
568        let expected = daml_value!("9999-12-31"::d);
569        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
570        assert_eq!(actual, expected);
571        Ok(())
572    }
573
574    /// `"0001-01-01"` -> `date 0001 Jan 01 : Text`
575    #[test]
576    fn test_date_max() -> DamlJsonCodecResult<()> {
577        let json_value = json!("0001-01-01");
578        let ty = DamlType::Date;
579        let expected = daml_value!("0001-01-01"::d);
580        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
581        assert_eq!(actual, expected);
582        Ok(())
583    }
584
585    /// `"9999-99-99"` -> `n/a : Text`
586    #[test]
587    fn test_date_invalid_fails() {
588        let json_value = json!("9999-99-99");
589        let ty = DamlType::Date;
590        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
591        assert!(actual.is_err());
592    }
593
594    /// `"1990-11-09T04:30:23.1234569Z"` -> `datetime 1990 Nov 09 04 30 23 xxx : Text`
595    #[test]
596    fn test_timestamp_full() -> DamlJsonCodecResult<()> {
597        let json_value = json!("1990-11-09T04:30:23.1234569Z");
598        let ty = DamlType::Timestamp;
599        let expected = daml_value!("1990-11-09T04:30:23.1234569Z"::t);
600        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
601        assert_eq!(actual, expected);
602        Ok(())
603    }
604
605    /// `"1990-11-09T04:30:23Z"` -> `datetime 1990 Nov 09 04 30 23 xxx : Text`
606    #[test]
607    fn test_timestamp_no_sub_sec() -> DamlJsonCodecResult<()> {
608        let json_value = json!("1990-11-09T04:30:23Z");
609        let ty = DamlType::Timestamp;
610        let expected = daml_value!("1990-11-09T04:30:23Z"::t);
611        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
612        assert_eq!(actual, expected);
613        Ok(())
614    }
615
616    /// `"1990-11-09T04:30:23.123Z"` -> `datetime 1990 Nov 09 04 30 23 xxx : Text`
617    #[test]
618    fn test_timestamp_no_micros() -> DamlJsonCodecResult<()> {
619        let json_value = json!("1990-11-09T04:30:23.123Z");
620        let ty = DamlType::Timestamp;
621        let expected = daml_value!("1990-11-09T04:30:23.123Z"::t);
622        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
623        assert_eq!(actual, expected);
624        Ok(())
625    }
626
627    /// `"0001-01-01T00:00:00Z"` -> `datetime 0001 Jan 01 00 00 00 xxx : Text`
628    #[test]
629    fn test_timestamp_min() -> DamlJsonCodecResult<()> {
630        let json_value = json!("0001-01-01T00:00:00Z");
631        let ty = DamlType::Timestamp;
632        let expected = daml_value!("0001-01-01T00:00:00Z"::t);
633        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
634        assert_eq!(actual, expected);
635        Ok(())
636    }
637
638    /// `"9999-12-31T23:59:59.999999Z"` -> `datetime 9999 Dec 12 59 59 59 xxx : Text`
639    #[test]
640    fn test_timestamp_max() -> DamlJsonCodecResult<()> {
641        let json_value = json!("9999-12-31T23:59:59.999999Z");
642        let ty = DamlType::Timestamp;
643        let expected = daml_value!("9999-12-31T23:59:59.999999Z"::t);
644        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
645        assert_eq!(actual, expected);
646        Ok(())
647    }
648
649    /// `"Alice"` -> `"Alice" : Party`
650    #[test]
651    fn test_party() -> DamlJsonCodecResult<()> {
652        let json_value = json!("Alice");
653        let ty = DamlType::Party;
654        let expected = daml_value!("Alice"::p);
655        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
656        assert_eq!(actual, expected);
657        Ok(())
658    }
659
660    /// `"foo:bar#baz"` -> `n/a : ContractId T`
661    #[test]
662    fn test_contract_id() -> DamlJsonCodecResult<()> {
663        let json_value = json!("foo:bar#baz");
664        let ty = DamlType::ContractId(None);
665        let expected = daml_value!("foo:bar#baz"::c);
666        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
667        assert_eq!(actual, expected);
668        Ok(())
669    }
670
671    /// `null` -> `None : Optional Int64`
672    #[test]
673    fn test_opt_int_null() -> DamlJsonCodecResult<()> {
674        let json_value = json!(null);
675        let ty = DamlType::Optional(vec![DamlType::Int64]);
676        let expected = daml_value!({?!});
677        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
678        assert_eq!(actual, expected);
679        Ok(())
680    }
681
682    /// `[]` -> `None : Optional Int64`
683    #[test]
684    fn test_opt_int_null_fails() {
685        let json_value = json!([]);
686        let ty = DamlType::Optional(vec![DamlType::Int64]);
687        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
688        assert!(actual.is_err());
689    }
690
691    /// `[null]` -> `Some None : Optional (Optional Int64)`
692    #[test]
693    fn test_opt_opt_int_some_should_fail() {
694        let json_value = json!([null]);
695        let ty = DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Int64])]);
696        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
697        assert!(actual.is_err());
698    }
699
700    /// `null` -> `None : Optional (Optional Int64)`
701    #[test]
702    fn test_opt_opt_int_null() -> DamlJsonCodecResult<()> {
703        let json_value = json!(null);
704        let ty = DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Int64])]);
705        let expected = daml_value!({?!});
706        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
707        assert_eq!(actual, expected);
708        Ok(())
709    }
710
711    /// `42` -> `Some 42 : Optional Int64`
712    #[test]
713    fn test_opt_int_some() -> DamlJsonCodecResult<()> {
714        let json_value = json!(42);
715        let ty = DamlType::Optional(vec![DamlType::Int64]);
716        let expected = daml_value!({?=42});
717        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
718        assert_eq!(actual, expected);
719        Ok(())
720    }
721
722    /// `[]` -> `Some None : Optional (Optional Int64)`
723    #[test]
724    fn test_opt_opt_int_some_none() -> DamlJsonCodecResult<()> {
725        let json_value = json!([]);
726        let ty = DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Int64])]);
727        let expected = daml_value!({?={?!}});
728        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
729        assert_eq!(actual, expected);
730        Ok(())
731    }
732
733    /// `[42]` -> `Some (Some 42) : Optional (Optional Int64)`
734    #[test]
735    fn test_opt_opt_int_some_some() -> DamlJsonCodecResult<()> {
736        let json_value = json!([42]);
737        let ty = DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Int64])]);
738        let expected = daml_value!({?={?=42}});
739        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
740        assert_eq!(actual, expected);
741        Ok(())
742    }
743
744    /// `[[]]` -> `Some (Some None) : Optional (Optional (Optional Int64))`
745    #[test]
746    fn test_opt_opt_opt_int_some_some_none() -> DamlJsonCodecResult<()> {
747        let json_value = json!([[]]);
748        let ty = DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Int64])])]);
749        let expected = daml_value!({?={?={?!}}});
750        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
751        assert_eq!(actual, expected);
752        Ok(())
753    }
754
755    /// `[[42]]` -> `Some (Some (Some 42)) : Optional (Optional (Optional Int64))`
756    #[test]
757    fn test_opt_opt_opt_int_some_some_some() -> DamlJsonCodecResult<()> {
758        let json_value = json!([[42]]);
759        let ty = DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Int64])])]);
760        let expected = daml_value!({?={?={?=42}}});
761        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
762        assert_eq!(actual, expected);
763        Ok(())
764    }
765
766    /// `[[[]]]` -> `Some (Some (Some None)) : Optional (Optional (Optional (Optional Int64)))`
767    #[test]
768    fn test_opt_opt_opt_opt_int_some_some_some_none() -> DamlJsonCodecResult<()> {
769        let json_value = json!([[[]]]);
770        let ty =
771            DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Optional(vec![
772                DamlType::Int64,
773            ])])])]);
774        let expected = daml_value!({?={?={?={?!}}}});
775        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
776        assert_eq!(actual, expected);
777        Ok(())
778    }
779
780    /// `[[[42]]]` -> `Some (Some (Some 42)) : Optional (Optional (Optional (Optional Int64)))`
781    #[test]
782    fn test_opt_opt_opt_opt_int_some_some_some_some() -> DamlJsonCodecResult<()> {
783        let json_value = json!([[[42]]]);
784        let ty =
785            DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Optional(vec![DamlType::Optional(vec![
786                DamlType::Int64,
787            ])])])]);
788        let expected = daml_value!({?={?={?={?=42}}}});
789        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
790        assert_eq!(actual, expected);
791        Ok(())
792    }
793
794    /// `null` -> `None : Optional Unit`
795    #[test]
796    fn test_opt_unit_null() -> DamlJsonCodecResult<()> {
797        let json_value = json!(null);
798        let ty = DamlType::Optional(vec![DamlType::Unit]);
799        let expected = daml_value!({?!});
800        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
801        assert_eq!(actual, expected);
802        Ok(())
803    }
804
805    /// `{}` -> `None : Optional Unit`
806    #[test]
807    fn test_opt_unit_some() -> DamlJsonCodecResult<()> {
808        let json_value = json!({});
809        let ty = DamlType::Optional(vec![DamlType::Unit]);
810        let expected = daml_value!({?=()});
811        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
812        assert_eq!(actual, expected);
813        Ok(())
814    }
815
816    /// `{ "landlord": "Alice", ... }` -> `RentalAgreement with landlord = "Alice"; ... : RentalAgreement`
817    #[test]
818    fn test_record() -> DamlJsonCodecResult<()> {
819        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
820        let json_value = json!({
821             "landlord": "Alice",
822             "tenant": "Bob",
823             "terms": "test terms",
824        });
825        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "RentDemo"], "RentalAgreement");
826        let expected = daml_value!({landlord: "Alice"::p, tenant: "Bob"::p, terms: "test terms"});
827        let actual = decode_apply(&dar, &json_value, &ty)?;
828        assert_eq!(actual, expected);
829        Ok(())
830    }
831
832    /// `{ "landlord": "Alice", ... }` -> `RentalAgreement with landlord = "Alice"; ... : RentalAgreement`
833    #[test]
834    fn test_record_array() -> DamlJsonCodecResult<()> {
835        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
836        let json_value = json!(["Alice", "Bob", 0]);
837        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "PingPong"], "Ping");
838        let expected = daml_value!({sender: "Alice"::p, receiver: "Bob"::p, count: 0});
839        let actual = decode_apply(&dar, &json_value, &ty)?;
840        assert_eq!(actual, expected);
841        Ok(())
842    }
843
844    /// `{}` -> `Depth1 with foo = None : data Depth1 = Depth1 with foo: Optional Int64`
845    #[test]
846    fn test_record_depth1_omitted() -> DamlJsonCodecResult<()> {
847        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
848        let json_value = json!({});
849        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Depth1");
850        let expected = daml_value!({foo: {?!}});
851        let actual = decode_apply(&dar, &json_value, &ty)?;
852        assert_eq!(actual, expected);
853        Ok(())
854    }
855
856    /// `{ "foo": null }` -> `Depth1 with foo = None : data Depth1 = Depth1 with foo: Optional Int64`
857    #[test]
858    fn test_record_depth1_none() -> DamlJsonCodecResult<()> {
859        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
860        let json_value = json!({ "foo": null });
861        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Depth1");
862        let expected = daml_value!({foo: {?!}});
863        let actual = decode_apply(&dar, &json_value, &ty)?;
864        assert_eq!(actual, expected);
865        Ok(())
866    }
867
868    /// `{ "foo": 42 }` -> `Depth1 with foo = Some 42 : data Depth1 = Depth1 with foo: Optional Int64`
869    #[test]
870    fn test_record_depth1_some() -> DamlJsonCodecResult<()> {
871        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
872        let json_value = json!({ "foo": 42 });
873        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Depth1");
874        let expected = daml_value!({foo: {?=42}});
875        let actual = decode_apply(&dar, &json_value, &ty)?;
876        assert_eq!(actual, expected);
877        Ok(())
878    }
879
880    /// `{}` -> `Depth2 with foo = None : data Depth2 = Depth2 with foo: Optional (Optional Int64)`
881    #[test]
882    fn test_record_depth2_omitted() -> DamlJsonCodecResult<()> {
883        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
884        let json_value = json!({});
885        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Depth2");
886        let expected = daml_value!({foo: {?!}});
887        let actual = decode_apply(&dar, &json_value, &ty)?;
888        assert_eq!(actual, expected);
889        Ok(())
890    }
891
892    /// `{ "foo": null }` -> `Depth2 with foo = None : data Depth2 = Depth2 with foo: Optional (Optional Int64)`
893    #[test]
894    fn test_record_depth2_none() -> DamlJsonCodecResult<()> {
895        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
896        let json_value = json!({ "foo": null });
897        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Depth2");
898        let expected = daml_value!({foo: {?!}});
899        let actual = decode_apply(&dar, &json_value, &ty)?;
900        assert_eq!(actual, expected);
901        Ok(())
902    }
903
904    /// `{ "foo": [] }` -> `Depth2 with foo = Some (None) : data Depth2 = Depth2 with foo: Optional (Optional Int64)`
905    #[test]
906    fn test_record_depth2_some_none() -> DamlJsonCodecResult<()> {
907        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
908        let json_value = json!({ "foo": [] });
909        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Depth2");
910        let expected = daml_value!({foo: {?={?!}}});
911        let actual = decode_apply(&dar, &json_value, &ty)?;
912        assert_eq!(actual, expected);
913        Ok(())
914    }
915
916    /// `{"foo": [42]}` -> `Depth2 with foo = Some (Some 42) : data Depth2 = Depth2 with foo: Optional (Optional Int64)`
917    #[test]
918    fn test_record_depth2_some_some() -> DamlJsonCodecResult<()> {
919        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
920        let json_value = json!({ "foo": [42] });
921        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Depth2");
922        let expected = daml_value!({foo: {?={?=42}}});
923        let actual = decode_apply(&dar, &json_value, &ty)?;
924        assert_eq!(actual, expected);
925        Ok(())
926    }
927
928    /// `[]` -> `[] : [Text]`
929    #[test]
930    fn test_list_bool_empty() -> DamlJsonCodecResult<()> {
931        let json_value = json!([]);
932        let ty = DamlType::List(vec![DamlType::Bool]);
933        let expected = daml_value!([]);
934        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
935        assert_eq!(actual, expected);
936        Ok(())
937    }
938
939    /// `["a", "b", "c"]` -> `["a", "b", "c"] : [Text]`
940    #[test]
941    fn test_list_text() -> DamlJsonCodecResult<()> {
942        let json_value = json!(["a", "b", "c"]);
943        let ty = DamlType::List(vec![DamlType::Text]);
944        let expected = daml_value!(["a", "b", "c"]);
945        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
946        assert_eq!(actual, expected);
947        Ok(())
948    }
949
950    /// `["a", null, "c"]` -> `[Some "a", None, Some "c"] : [Optional Text]`
951    #[test]
952    fn test_list_opt_text() -> DamlJsonCodecResult<()> {
953        let json_value = json!(["a", null, "c"]);
954        let ty = DamlType::List(vec![DamlType::Optional(vec![DamlType::Text])]);
955        let expected = daml_value!([{?="a"}, {?!}, {?="c"}]);
956        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
957        assert_eq!(actual, expected);
958        Ok(())
959    }
960
961    /// `[42, null, "c"]` -> n/a (error case)
962    #[test]
963    fn test_list_opt_mixed_fails() {
964        let json_value = json!([42, null, "c"]);
965        let ty = DamlType::List(vec![DamlType::Optional(vec![DamlType::Text])]);
966        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
967        assert!(actual.is_err());
968    }
969
970    /// `[{...}]` -> `[RentalAgreement with landlord = "..."; tenant = "..."; terms = "..."] : [RentalAgreement]`
971    #[test]
972    fn test_list_record() -> DamlJsonCodecResult<()> {
973        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
974        let json_value = json!([{
975            "landlord": "Alice",
976            "tenant": "Bob",
977            "terms": "test terms",
978        },
979        {
980            "landlord": "John",
981            "tenant": "Paul",
982            "terms": "more test terms",
983        }]);
984        let ty = DamlType::List(vec![DamlType::make_tycon(&dar.main.hash, &["Fuji", "RentDemo"], "RentalAgreement")]);
985        let expected = daml_value!([{
986            landlord: "Alice"::p,
987            tenant: "Bob"::p,
988            terms: "test terms"
989        },
990        {
991            landlord: "John"::p,
992            tenant: "Paul"::p,
993            terms: "more test terms"
994        }]);
995        let actual = decode_apply(&dar, &json_value, &ty)?;
996        assert_eq!(actual, expected);
997        Ok(())
998    }
999
1000    /// `{}` -> `M.fromList [] : Map Int`
1001    #[test]
1002    fn test_textmap_int_empty() -> DamlJsonCodecResult<()> {
1003        let json_value = json!({});
1004        let ty = DamlType::TextMap(vec![DamlType::Int64]);
1005        let expected = DamlValue::Map(vec![].into_iter().collect());
1006        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
1007        assert_eq!(actual, expected);
1008        Ok(())
1009    }
1010
1011    /// `{"foo": 42, "bar": 43}` -> `M.fromList [("foo", 42), ("bar", 43)] : Map Int`
1012    #[test]
1013    fn test_textmap_int() -> DamlJsonCodecResult<()> {
1014        let json_value = json!({"foo": 42, "bar": 43});
1015        let ty = DamlType::TextMap(vec![DamlType::Int64]);
1016        let expected = DamlValue::Map(
1017            vec![("foo".to_owned(), daml_value![42]), ("bar".to_owned(), daml_value![43])].into_iter().collect(),
1018        );
1019        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
1020        assert_eq!(actual, expected);
1021        Ok(())
1022    }
1023
1024    /// `[{"foo": 42}, {"bar": 43}]` -> `[M.fromList [("foo", 42)], M.fromList [("bar", 43)]] : [Map Int]`
1025    #[test]
1026    fn test_list_textmap_int() -> DamlJsonCodecResult<()> {
1027        let json_value = json!([{"foo": 42}, {"bar": 43}]);
1028        let ty = DamlType::List(vec![DamlType::TextMap(vec![DamlType::Int64])]);
1029        let expected = daml_value![[
1030            (DamlValue::Map(DamlTextMap::from(hashmap! {"foo".to_owned() => daml_value![42]}))),
1031            (DamlValue::Map(DamlTextMap::from(hashmap! {"bar".to_owned() => daml_value![43]})))
1032        ]];
1033        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
1034        assert_eq!(actual, expected);
1035        Ok(())
1036    }
1037
1038    /// `{"foo": [1, 2, 3], "bar": [4, 5, 6]}` -> `M.fromList [("foo", [1, 2, 3]), ("bar", [4, 5, 6])] : Map [Int]`
1039    #[test]
1040    fn test_textmap_list_int() -> DamlJsonCodecResult<()> {
1041        let json_value = json!({"foo": [1, 2, 3], "bar": [4, 5, 6]});
1042        let ty = DamlType::TextMap(vec![DamlType::List(vec![DamlType::Int64])]);
1043        let expected = DamlValue::Map(DamlTextMap::from(hashmap! {
1044            "foo".to_owned() => daml_value![[1, 2, 3]],
1045            "bar".to_owned() => daml_value![[4, 5, 6]]
1046        }));
1047        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
1048        assert_eq!(actual, expected);
1049        Ok(())
1050    }
1051
1052    /// `{"first": {...}, last: {...}}` -> `M.fromList [("first", Agreement with ...)] : Map Agreement`
1053    #[test]
1054    fn test_textmap_record() -> DamlJsonCodecResult<()> {
1055        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1056        let json_value = json!({
1057        "first": {
1058            "landlord": "Alice",
1059            "tenant": "Bob",
1060            "terms": "test terms",
1061        },
1062        "last": {
1063            "landlord": "John",
1064            "tenant": "Paul",
1065            "terms": "more test terms",
1066        }});
1067        let ty =
1068            DamlType::TextMap(vec![DamlType::make_tycon(&dar.main.hash, &["Fuji", "RentDemo"], "RentalAgreement")]);
1069        let expected = DamlValue::Map(DamlTextMap::from(hashmap! {
1070            "first".to_owned() => daml_value!({landlord: "Alice"::p, tenant: "Bob"::p, terms: "test terms"}),
1071            "last".to_owned() => daml_value!({landlord: "John"::p, tenant: "Paul"::p, terms: "more test terms"})
1072        }));
1073        let actual = decode_apply(&dar, &json_value, &ty)?;
1074        assert_eq!(actual, expected);
1075        Ok(())
1076    }
1077
1078    /// `[]` -> `M.fromList [] : Map Int`
1079    #[test]
1080    fn test_genmap_int_empty() -> DamlJsonCodecResult<()> {
1081        let json_value = json!([]);
1082        let ty = DamlType::GenMap(vec![DamlType::Int64]);
1083        let expected = DamlValue::GenMap(vec![].into_iter().collect());
1084        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
1085        assert_eq!(actual, expected);
1086        Ok(())
1087    }
1088
1089    /// `[["foo", 42], ["bar", 43]]` -> `M.fromList [("foo", 42), ("bar", 43)] : Map Int`
1090    #[test]
1091    fn test_genmap_string_to_int() -> DamlJsonCodecResult<()> {
1092        let json_value = json!([["foo", 42], ["bar", 43]]);
1093        let ty = DamlType::GenMap(vec![DamlType::Text, DamlType::Int64]);
1094        let expected = DamlValue::GenMap(
1095            vec![(daml_value!["foo"], daml_value![42]), (daml_value!["bar"], daml_value![43])].into_iter().collect(),
1096        );
1097        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
1098        assert_eq!(actual, expected);
1099        Ok(())
1100    }
1101
1102    /// `[[42, "foo"], [43, "bar"]]` -> `M.fromList [(42, "foo"), (43, "bar")] : Map Int`
1103    #[test]
1104    fn test_genmap_int_to_string() -> DamlJsonCodecResult<()> {
1105        let json_value = json!([[42, "foo"], [43, "bar"]]);
1106        let ty = DamlType::GenMap(vec![DamlType::Int64, DamlType::Text]);
1107        let expected = DamlValue::GenMap(
1108            vec![(daml_value![42], daml_value!["foo"]), (daml_value![43], daml_value!["bar"])].into_iter().collect(),
1109        );
1110        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty)?;
1111        assert_eq!(actual, expected);
1112        Ok(())
1113    }
1114
1115    /// `[[{"name": "Alice", "age": 30}, "foo"], [{"name": "Bob", "age": 18}, "bar"]]` -> `M.fromList [(Person "Alice"
1116    /// 30, "foo"), (Person "Bob" 18, "bar")] : Map Person Text`
1117    #[test]
1118    fn test_genmap_person_to_string() -> DamlJsonCodecResult<()> {
1119        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1120        let json_value = json!([[{"name": "Alice", "age": 30}, "foo"], [{"name": "Bob", "age": 18}, "bar"]]);
1121        let key_type = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Person");
1122        let value_type = DamlType::Text;
1123        let ty = DamlType::GenMap(vec![key_type, value_type]);
1124        let expected = DamlValue::GenMap(
1125            vec![
1126                (daml_value![{name: "Alice", age: 30}], daml_value!["foo"]),
1127                (daml_value![{name: "Bob", age: 18}], daml_value!["bar"]),
1128            ]
1129            .into_iter()
1130            .collect(),
1131        );
1132        let actual = decode_apply(&dar, &json_value, &ty)?;
1133        assert_eq!(actual, expected);
1134        Ok(())
1135    }
1136
1137    #[test]
1138    fn test_genmap_duplicate_key_should_fail() {
1139        let json_value = json!([[42, "foo"], [42, "bar"]]);
1140        let ty = DamlType::GenMap(vec![DamlType::Int64, DamlType::Text]);
1141        let actual = JsonValueDecoder::new(&DamlArchive::default()).decode(&json_value, &ty);
1142        assert!(actual.is_err());
1143    }
1144
1145    /// `{"tag": "Bar", "value": 42}` -> `Bar 42 : variant Foo = Bar Int64 | Baz | Quux (Optional Int64)`
1146    #[test]
1147    fn test_variant_bar() -> DamlJsonCodecResult<()> {
1148        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1149        let json_value = json!({"tag": "Bar", "value": 42});
1150        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Foo");
1151        let expected = daml_value![{=>Bar 42}];
1152        let actual = decode_apply(&dar, &json_value, &ty)?;
1153        assert_eq!(actual, expected);
1154        Ok(())
1155    }
1156
1157    /// `{"tag": "Baz", "value": {}}` -> `Baz : variant Foo = Bar Int64 | Baz | Quux (Optional Int64)`
1158    #[test]
1159    fn test_variant_baz() -> DamlJsonCodecResult<()> {
1160        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1161        let json_value = json!({"tag": "Baz", "value": {}});
1162        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Foo");
1163        let expected = daml_value![{=>Baz}];
1164        let actual = decode_apply(&dar, &json_value, &ty)?;
1165        assert_eq!(actual, expected);
1166        Ok(())
1167    }
1168
1169    /// `{"tag": "Quux", "value": null}` -> `Quux None : variant Foo = Bar Int64 | Baz | Quux (Optional Int64)`
1170    #[test]
1171    fn test_variant_quux_none() -> DamlJsonCodecResult<()> {
1172        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1173        let json_value = json!({"tag": "Quux", "value": null});
1174        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Foo");
1175        let expected = daml_value![{=>Quux {?!}}];
1176        let actual = decode_apply(&dar, &json_value, &ty)?;
1177        assert_eq!(actual, expected);
1178        Ok(())
1179    }
1180
1181    /// `{"tag": "Quux", "value": 42}` -> `Quux Some 42 : variant Foo = Bar Int64 | Baz | Quux (Optional Int64)`
1182    #[test]
1183    fn test_variant_quux_some() -> DamlJsonCodecResult<()> {
1184        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1185        let json_value = json!({"tag": "Quux", "value": 42});
1186        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Foo");
1187        let expected = daml_value![{=>Quux {?=42}}];
1188        let actual = decode_apply(&dar, &json_value, &ty)?;
1189        assert_eq!(actual, expected);
1190        Ok(())
1191    }
1192
1193    /// `Enabled` -> `Enabled : data Status = Enabled | Disabled`
1194    #[test]
1195    fn test_enum_enabled() -> DamlJsonCodecResult<()> {
1196        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1197        let json_value = json!("Enabled");
1198        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Status");
1199        let expected = DamlValue::Enum(DamlEnum::new("Enabled", None));
1200        let actual = decode_apply(&dar, &json_value, &ty)?;
1201        assert_eq!(actual, expected);
1202        Ok(())
1203    }
1204
1205    /// `Disabled` -> `Enabled : data Status = Enabled | Disabled`
1206    #[test]
1207    fn test_enum_disabled() -> DamlJsonCodecResult<()> {
1208        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1209        let json_value = json!("Disabled");
1210        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Status");
1211        let expected = DamlValue::Enum(DamlEnum::new("Disabled", None));
1212        let actual = decode_apply(&dar, &json_value, &ty)?;
1213        assert_eq!(actual, expected);
1214        Ok(())
1215    }
1216
1217    /// `Unknown` -> `Enabled : data Status = Enabled | Disabled`
1218    #[test]
1219    fn test_enum_unknown_error() -> DamlJsonCodecResult<()> {
1220        let dar = DarFile::from_file(TESTING_TYPES_DAR_PATH)?;
1221        let json_value = json!("Unknown");
1222        let ty = DamlType::make_tycon(&dar.main.hash, &["Fuji", "JsonTest"], "Status");
1223        let actual = decode_apply(&dar, &json_value, &ty);
1224        assert!(actual.is_err());
1225        Ok(())
1226    }
1227
1228    fn decode_apply(dar: &DarFile, json_value: &Value, ty: &DamlType<'_>) -> DamlJsonCodecResult<DamlValue> {
1229        dar.apply(|arc| {
1230            let decoded_value = JsonValueDecoder::new(arc).decode(json_value, ty)?;
1231            Ok::<DamlValue, DamlJsonCodecError>(decoded_value)
1232        })?
1233    }
1234}