daml_grpc/data/value/
values.rs

1use crate::data::value::{DamlEnum, DamlRecord, DamlVariant};
2use crate::data::{DamlError, DamlResult};
3use crate::grpc_protobuf::com::daml::ledger::api::v1::value::Sum;
4use crate::grpc_protobuf::com::daml::ledger::api::v1::{
5    gen_map, map, Enum, GenMap, List, Map, Optional, Record, Value, Variant,
6};
7use crate::util;
8use crate::util::Required;
9use std::convert::{TryFrom, TryInto};
10
11use crate::nat::Nat;
12use crate::primitive_types::{
13    DamlBool, DamlContractId, DamlDate, DamlFixedNumeric, DamlGenMap, DamlInt64, DamlList, DamlNumeric, DamlOptional,
14    DamlParty, DamlText, DamlTextMap, DamlTimestamp, DamlUnit,
15};
16use crate::serialize::{
17    DamlDeserializableType, DamlDeserializeFrom, DamlDeserializeInto, DamlSerializableType, DamlSerializeFrom,
18    DamlSerializeInto,
19};
20use itertools::Itertools;
21use std::cmp::Ordering;
22use std::str::FromStr;
23
24/// A generic representation of data on a Daml ledger.
25///
26/// See the documentation for the Daml GRPC [Value](https://docs.daml.com/app-dev/grpc/proto-docs.html#value) type for
27/// details.
28///
29/// The [`daml_value!`] macro can be used simplify the construction of complex [`DamlValue`] values.
30///
31/// [`daml_value!`]: https://docs.rs/daml-macro/0.2.2/daml_macro/macro.daml_value.html
32#[derive(Debug, Eq, PartialEq, Clone)]
33pub enum DamlValue {
34    /// A Daml [`Record`](https://docs.daml.com/app-dev/grpc/proto-docs.html#record) value.
35    Record(DamlRecord),
36    /// A Daml [`Variant`](https://docs.daml.com/app-dev/grpc/proto-docs.html#variant) value.
37    Variant(DamlVariant),
38    /// A Daml [`Enum`](https://docs.daml.com/app-dev/grpc/proto-docs.html#enum) value.
39    Enum(DamlEnum),
40    /// A Daml `ContractId`.
41    ContractId(DamlContractId),
42    /// A Daml [`List`](https://docs.daml.com/app-dev/grpc/proto-docs.html#list) value.
43    List(DamlList<DamlValue>),
44    /// A Daml signed 64 bit integer value.
45    Int64(DamlInt64),
46    /// A Daml fixed precision numeric value.
47    Numeric(DamlNumeric),
48    /// A Daml text string value.
49    Text(DamlText),
50    /// A Daml timestamp value.
51    Timestamp(DamlTimestamp),
52    /// A Daml Party value.
53    Party(DamlParty),
54    /// A Daml boolean value.
55    Bool(DamlBool),
56    /// A Daml unit value.
57    Unit,
58    /// A Daml date value.
59    Date(DamlDate),
60    /// A Daml [optional value.
61    Optional(Option<Box<DamlValue>>),
62    /// A Daml [`Map`](https://docs.daml.com/app-dev/grpc/proto-docs.html#map) value.
63    Map(DamlTextMap<DamlValue>),
64    /// A Daml [`GenMap`](https://docs.daml.com/app-dev/grpc/proto-docs.html#genmap) value.
65    GenMap(DamlGenMap<DamlValue, DamlValue>),
66}
67
68impl DamlValue {
69    /// Construct a new [`DamlValue::Record`] from an existing [`DamlRecord`].
70    pub fn new_record(record: impl Into<DamlRecord>) -> Self {
71        DamlValue::Record(record.into())
72    }
73
74    /// Construct a new [`DamlValue::Variant`] from an existing [`DamlVariant`].
75    pub fn new_variant(variant: impl Into<DamlVariant>) -> Self {
76        DamlValue::Variant(variant.into())
77    }
78
79    /// Construct a new [`DamlValue::Enum`] from an existing [`DamlEnum`].
80    pub fn new_enum(enum_variant: impl Into<DamlEnum>) -> Self {
81        DamlValue::Enum(enum_variant.into())
82    }
83
84    /// Construct a new [`DamlValue::ContractId`] from an existing [`DamlContractId`].
85    pub fn new_contract_id(contract_id: impl Into<DamlContractId>) -> Self {
86        DamlValue::ContractId(contract_id.into())
87    }
88
89    /// Construct a new [`DamlValue::List`] from an existing [`DamlList<DamlValue>`].
90    pub fn new_list(list: impl Into<DamlList<Self>>) -> Self {
91        DamlValue::List(list.into())
92    }
93
94    /// Construct a new [`DamlValue::Int64`] from an existing [`DamlInt64`].
95    pub fn new_int64(value: impl Into<DamlInt64>) -> Self {
96        DamlValue::Int64(value.into())
97    }
98
99    /// Construct a new [`DamlValue::Numeric`] from an existing [`DamlNumeric`].
100    pub fn new_numeric(numeric: impl Into<DamlNumeric>) -> Self {
101        DamlValue::Numeric(numeric.into())
102    }
103
104    /// Construct a new [`DamlValue::Text`] from an existing [`DamlText`].
105    pub fn new_text(text: impl Into<DamlText>) -> Self {
106        DamlValue::Text(text.into())
107    }
108
109    /// Construct a new [`DamlValue::Timestamp`] from an existing [`DamlTimestamp`].
110    pub fn new_timestamp(timestamp: impl Into<DamlTimestamp>) -> Self {
111        DamlValue::Timestamp(timestamp.into())
112    }
113
114    /// Construct a new [`DamlValue::Party`] from an existing [`DamlParty`].
115    pub fn new_party(party: impl Into<DamlParty>) -> Self {
116        DamlValue::Party(party.into())
117    }
118
119    /// Construct a new [`DamlValue::Bool`] from an existing [`DamlBool`].
120    pub fn new_bool(value: DamlBool) -> Self {
121        DamlValue::Bool(value)
122    }
123
124    /// Construct a new [`DamlValue::Unit`].
125    pub const fn new_unit() -> Self {
126        DamlValue::Unit
127    }
128
129    /// Construct a new [`DamlValue::Date`] from an existing [`DamlDate`].
130    pub fn new_date(date: impl Into<DamlDate>) -> Self {
131        DamlValue::Date(date.into())
132    }
133
134    /// Construct a new [`DamlValue::Optional`] from an existing [`Option<DamlValue>`].
135    pub fn new_optional(optional: Option<Self>) -> Self {
136        DamlValue::Optional(optional.map(Box::new))
137    }
138
139    /// Construct a new [`DamlValue::Map`] from an existing [`DamlTextMap<DamlValue>`].
140    pub fn new_map(map: impl Into<DamlTextMap<Self>>) -> Self {
141        DamlValue::Map(map.into())
142    }
143
144    /// Construct a new [`DamlValue::GenMap`] from an existing [`DamlGenMap<DamlValue, DamlValue>`].
145    pub fn new_genmap(map: impl Into<DamlGenMap<Self, Self>>) -> Self {
146        DamlValue::GenMap(map.into())
147    }
148
149    /// Try to extract an `()` value from the [`DamlValue`].
150    ///
151    /// if `self` is a [`DamlValue::Unit`] then `()` is returned, otherwise a [`DamlError::UnexpectedType`] is
152    /// returned.
153    pub fn try_unit(&self) -> DamlResult<()> {
154        match self {
155            DamlValue::Unit => Ok(()),
156            _ => Err(self.make_unexpected_type_error("Unit")),
157        }
158    }
159
160    /// Try to extract an `&()` value from the [`DamlValue`].
161    ///
162    /// if `self` is a [`DamlValue::Unit`] then `&()` is returned, otherwise a [`DamlError::UnexpectedType`] is
163    /// returned.
164    pub fn try_unit_ref(&self) -> DamlResult<&()> {
165        match self {
166            DamlValue::Unit => Ok(&()),
167            _ => Err(self.make_unexpected_type_error("Unit")),
168        }
169    }
170
171    /// Try to extract an [`DamlDate`] value from the [`DamlValue`].
172    ///
173    /// if `self` is a [`DamlValue::Date`] then [`DamlDate`] is returned, otherwise a [`DamlError::UnexpectedType`] is
174    /// returned.
175    pub fn try_date(&self) -> DamlResult<DamlDate> {
176        match *self {
177            DamlValue::Date(d) => Ok(d),
178            _ => Err(self.make_unexpected_type_error("Date")),
179        }
180    }
181
182    /// Try to extract an &[`DamlDate`] value from the [`DamlValue`].
183    ///
184    /// if `self` is a [`DamlValue::Date`] then &[`DamlDate`] is returned, otherwise a [`DamlError::UnexpectedType`] is
185    /// returned.
186    pub fn try_date_ref(&self) -> DamlResult<&DamlDate> {
187        match self {
188            DamlValue::Date(d) => Ok(d),
189            _ => Err(self.make_unexpected_type_error("Date")),
190        }
191    }
192
193    /// Try to extract an [`DamlInt64`] value from the [`DamlValue`].
194    ///
195    /// if `self` is a [`DamlValue::Int64`] then [`DamlInt64`] is returned, otherwise a [`DamlError::UnexpectedType`] is
196    /// returned.
197    pub fn try_int64(&self) -> DamlResult<DamlInt64> {
198        match self {
199            DamlValue::Int64(i) => Ok(*i),
200            _ => Err(self.make_unexpected_type_error("Int64")),
201        }
202    }
203
204    /// Try to extract an &[`DamlInt64`] value from the [`DamlValue`].
205    ///
206    /// if `self` is a [`DamlValue::Int64`] then &[`DamlInt64`] is returned, otherwise a [`DamlError::UnexpectedType`]
207    /// is returned.
208    pub fn try_int64_ref(&self) -> DamlResult<&DamlInt64> {
209        match self {
210            DamlValue::Int64(i) => Ok(i),
211            _ => Err(self.make_unexpected_type_error("Int64")),
212        }
213    }
214
215    /// Try to extract an &[`DamlNumeric`] value from the [`DamlValue`].
216    ///
217    /// if `self` is a [`DamlValue::Numeric`] then &[`DamlNumeric`] is returned, otherwise a
218    /// [`DamlError::UnexpectedType`] is returned.
219    pub fn try_numeric(&self) -> DamlResult<&DamlNumeric> {
220        match self {
221            DamlValue::Numeric(d) => Ok(d),
222            _ => Err(self.make_unexpected_type_error("Numeric")),
223        }
224    }
225
226    /// Try to extract an [`DamlNumeric`] value from the [`DamlValue`].
227    ///
228    /// if `self` is a [`DamlValue::Numeric`] then a clone of the [`DamlNumeric`] is returned, otherwise a
229    /// [`DamlError::UnexpectedType`] is returned.
230    pub fn try_numeric_clone(&self) -> DamlResult<DamlNumeric> {
231        match self {
232            DamlValue::Numeric(d) => Ok(d.clone()),
233            _ => Err(self.make_unexpected_type_error("Numeric")),
234        }
235    }
236
237    /// Try to extract an [`DamlBool`] value from the [`DamlValue`].
238    ///
239    /// if `self` is a [`DamlValue::Bool`] then [`DamlBool`] is returned, otherwise a [`DamlError::UnexpectedType`] is
240    /// returned.
241    pub fn try_bool(&self) -> DamlResult<DamlBool> {
242        match self {
243            DamlValue::Bool(b) => Ok(*b),
244            _ => Err(self.make_unexpected_type_error("Bool")),
245        }
246    }
247
248    /// Try to extract an &[`DamlBool`] value from the [`DamlValue`].
249    ///
250    /// if `self` is a [`DamlValue::Bool`] then &[`DamlBool`] is returned, otherwise a [`DamlError::UnexpectedType`] is
251    /// returned.
252    pub fn try_bool_ref(&self) -> DamlResult<&DamlBool> {
253        match self {
254            DamlValue::Bool(b) => Ok(b),
255            _ => Err(self.make_unexpected_type_error("Bool")),
256        }
257    }
258
259    /// Try to extract an &[`DamlText`] value from the [`DamlValue`].
260    ///
261    /// if `self` is a [`DamlValue::Text`] then &[`DamlText`] is returned, otherwise a [`DamlError::UnexpectedType`] is
262    /// returned.
263    pub fn try_text(&self) -> DamlResult<&DamlText> {
264        match self {
265            DamlValue::Text(s) => Ok(s),
266            _ => Err(self.make_unexpected_type_error("Text")),
267        }
268    }
269
270    /// Try to extract an [`DamlTimestamp`] value from the [`DamlValue`].
271    ///
272    /// if `self` is a [`DamlValue::Timestamp`] then [`DamlTimestamp`] is returned, otherwise a
273    /// [`DamlError::UnexpectedType`] is returned.
274    pub fn try_timestamp(&self) -> DamlResult<DamlTimestamp> {
275        match *self {
276            DamlValue::Timestamp(ts) => Ok(ts),
277            _ => Err(self.make_unexpected_type_error("Timestamp")),
278        }
279    }
280
281    /// Try to extract an &[`DamlTimestamp`] value from the [`DamlValue`].
282    ///
283    /// if `self` is a [`DamlValue::Timestamp`] then &[`DamlTimestamp`] is returned, otherwise a
284    /// [`DamlError::UnexpectedType`] is returned.
285    pub fn try_timestamp_ref(&self) -> DamlResult<&DamlTimestamp> {
286        match self {
287            DamlValue::Timestamp(ts) => Ok(ts),
288            _ => Err(self.make_unexpected_type_error("Timestamp")),
289        }
290    }
291
292    /// Try to extract an &[`DamlParty`] value from the [`DamlValue`].
293    ///
294    /// if `self` is a [`DamlValue::Party`] then &[`DamlParty`] is returned, otherwise a [`DamlError::UnexpectedType`]
295    /// is returned.
296    pub fn try_party(&self) -> DamlResult<&DamlParty> {
297        match self {
298            DamlValue::Party(party) => Ok(party),
299            _ => Err(self.make_unexpected_type_error("Party")),
300        }
301    }
302
303    /// Try to extract an &[`DamlContractId`] value from the [`DamlValue`].
304    ///
305    /// if `self` is a [`DamlValue::ContractId`] then &[`DamlContractId`] is returned, otherwise a
306    /// [`DamlError::UnexpectedType`] is returned.
307    pub fn try_contract_id(&self) -> DamlResult<&DamlContractId> {
308        match self {
309            DamlValue::ContractId(contract_id) => Ok(contract_id),
310            _ => Err(self.make_unexpected_type_error("ContractId")),
311        }
312    }
313
314    /// Try to extract an &[`DamlRecord`] value from the [`DamlValue`].
315    ///
316    /// if `self` is a [`DamlValue::Record`] then &[`DamlRecord`] is returned, otherwise a [`DamlError::UnexpectedType`]
317    /// is returned.
318    pub fn try_record(&self) -> DamlResult<&DamlRecord> {
319        match self {
320            DamlValue::Record(r) => Ok(r),
321            _ => Err(self.make_unexpected_type_error("Record")),
322        }
323    }
324
325    /// Try to extract an &[`DamlList<DamlValue>`] value from the [`DamlValue`].
326    ///
327    /// if `self` is a [`DamlValue::List`] then &[`DamlList<DamlValue>`] is returned, otherwise a
328    /// [`DamlError::UnexpectedType`] is returned.
329    pub fn try_list(&self) -> DamlResult<&DamlList<Self>> {
330        match self {
331            DamlValue::List(l) => Ok(l),
332            _ => Err(self.make_unexpected_type_error("List")),
333        }
334    }
335
336    /// Try to extract an &[`DamlVariant`] value from the [`DamlValue`].
337    ///
338    /// if `self` is a [`DamlValue::Variant`] then &[`DamlVariant`] is returned, otherwise a
339    /// [`DamlError::UnexpectedType`] is returned.
340    pub fn try_variant(&self) -> DamlResult<&DamlVariant> {
341        match self {
342            DamlValue::Variant(v) => Ok(v),
343            _ => Err(self.make_unexpected_type_error("Variant")),
344        }
345    }
346
347    /// Try to extract an &[`DamlEnum`] value from the [`DamlValue`].
348    ///
349    /// if `self` is a [`DamlValue::Enum`] then &[`DamlEnum`] is returned, otherwise a [`DamlError::UnexpectedType`] is
350    /// returned.
351    pub fn try_enum(&self) -> DamlResult<&DamlEnum> {
352        match self {
353            DamlValue::Enum(e) => Ok(e),
354            _ => Err(self.make_unexpected_type_error("Enum")),
355        }
356    }
357
358    /// Try to extract an [`Option<&Self>`] value from the [`DamlValue`].
359    ///
360    /// if `self` is a [`DamlValue::Optional`] then [`Option<&Self>`] is returned, otherwise a
361    /// [`DamlError::UnexpectedType`] is returned.
362    pub fn try_optional(&self) -> DamlResult<Option<&Self>> {
363        match self {
364            DamlValue::Optional(opt) => Ok(opt.as_deref()),
365            _ => Err(self.make_unexpected_type_error("Optional")),
366        }
367    }
368
369    /// Try to extract an &[`DamlTextMap<DamlValue>`] value from the [`DamlValue`].
370    ///
371    /// if `self` is a [`DamlValue::Map`] then &[`DamlTextMap<DamlValue>`] is returned, otherwise a
372    /// [`DamlError::UnexpectedType`] is returned.
373    pub fn try_map(&self) -> DamlResult<&DamlTextMap<Self>> {
374        match self {
375            DamlValue::Map(m) => Ok(m),
376            _ => Err(self.make_unexpected_type_error("Map")),
377        }
378    }
379
380    /// Try to extract an &[`DamlGenMap<DamlValue, DamlValue>`] value from the [`DamlValue`].
381    ///
382    /// if `self` is a [`DamlValue::GenMap`] then &[`DamlGenMap<DamlValue, DamlValue>`] is returned, otherwise a
383    /// [`DamlError::UnexpectedType`] is returned.
384    pub fn try_genmap(&self) -> DamlResult<&DamlGenMap<Self, Self>> {
385        match self {
386            DamlValue::GenMap(m) => Ok(m),
387            _ => Err(self.make_unexpected_type_error("GenMap")),
388        }
389    }
390
391    /// Try to take an [`DamlRecord`] value from the [`DamlValue`].
392    ///
393    /// if `self` is a [`DamlValue::Record`] then [`DamlRecord`] is returned, otherwise a
394    /// [`DamlError::UnexpectedType`] is returned.
395    pub fn try_take_record(self) -> DamlResult<DamlRecord> {
396        match self {
397            DamlValue::Record(r) => Ok(r),
398            _ => Err(self.make_unexpected_type_error("Record")),
399        }
400    }
401
402    /// Try to take an [`DamlVariant`] value from the [`DamlValue`].
403    ///
404    /// if `self` is a [`DamlValue::Variant`] then [`DamlVariant`] is returned, otherwise a
405    /// [`DamlError::UnexpectedType`] is returned.
406    pub fn try_take_variant(self) -> DamlResult<DamlVariant> {
407        match self {
408            DamlValue::Variant(v) => Ok(v),
409            _ => Err(self.make_unexpected_type_error("Variant")),
410        }
411    }
412
413    /// Try to take an [`DamlEnum`] value from the [`DamlValue`].
414    ///
415    /// if `self` is a [`DamlValue::Enum`] then [`DamlEnum`] is returned, otherwise a
416    /// [`DamlError::UnexpectedType`] is returned.
417    pub fn try_take_enum(self) -> DamlResult<DamlEnum> {
418        match self {
419            DamlValue::Enum(e) => Ok(e),
420            _ => Err(self.make_unexpected_type_error("Enum")),
421        }
422    }
423
424    /// Try to take an [`DamlList<DamlValue>`] value from the [`DamlValue`].
425    ///
426    /// if `self` is a [`DamlValue::List`] then [`DamlList<DamlValue>`] is returned, otherwise a
427    /// [`DamlError::UnexpectedType`] is returned.
428    pub fn try_take_list(self) -> DamlResult<DamlList<Self>> {
429        match self {
430            DamlValue::List(l) => Ok(l),
431            _ => Err(self.make_unexpected_type_error("List")),
432        }
433    }
434
435    /// Try to take an [`DamlTextMap<DamlValue>`] value from the [`DamlValue`].
436    ///
437    /// if `self` is a [`DamlValue::Map`] then [`DamlTextMap<DamlValue>`] is returned, otherwise a
438    /// [`DamlError::UnexpectedType`] is returned.
439    pub fn try_take_map(self) -> DamlResult<DamlTextMap<Self>> {
440        match self {
441            DamlValue::Map(m) => Ok(m),
442            _ => Err(self.make_unexpected_type_error("Map")),
443        }
444    }
445
446    /// Try to take an [`DamlGenMap<DamlValue, DamlValue>`] value from the [`DamlValue`].
447    ///
448    /// if `self` is a [`DamlValue::GenMap`] then [`DamlGenMap<DamlValue, DamlValue>`] is returned, otherwise a
449    /// [`DamlError::UnexpectedType`] is returned.
450    pub fn try_take_genmap(self) -> DamlResult<DamlGenMap<Self, Self>> {
451        match self {
452            DamlValue::GenMap(m) => Ok(m),
453            _ => Err(self.make_unexpected_type_error("Map")),
454        }
455    }
456
457    /// Try to take an [`Option<DamlValue>`] value from the [`DamlValue`].
458    ///
459    /// if `self` is a [`DamlValue::Optional`] then [`Option<DamlValue>`] is returned, otherwise a
460    /// [`DamlError::UnexpectedType`] is returned.
461    pub fn try_take_optional(self) -> DamlResult<Option<Self>> {
462        match self {
463            DamlValue::Optional(o) => Ok(o.map(|b| *b)),
464            _ => Err(self.make_unexpected_type_error("Optional")),
465        }
466    }
467
468    /// The name of this [`DamlValue`] variant type.
469    pub fn variant_name(&self) -> &str {
470        match self {
471            DamlValue::Record(_) => "Record",
472            DamlValue::Variant(_) => "Variant",
473            DamlValue::Enum(_) => "Enum",
474            DamlValue::ContractId(_) => "ContractId",
475            DamlValue::List(_) => "List",
476            DamlValue::Int64(_) => "Int64",
477            DamlValue::Numeric(_) => "Numeric",
478            DamlValue::Text(_) => "Text",
479            DamlValue::Timestamp(_) => "Timestamp",
480            DamlValue::Party(_) => "Party",
481            DamlValue::Bool(_) => "Bool",
482            DamlValue::Unit => "Unit",
483            DamlValue::Date(_) => "Date",
484            DamlValue::Optional(_) => "Optional",
485            DamlValue::Map(_) => "Map",
486            DamlValue::GenMap(_) => "GenMap",
487        }
488    }
489
490    /// Apply a Daml data extractor function.
491    ///
492    /// A Daml data extractor function has the following signature:
493    ///
494    /// `Fn(&DamlRecord) -> DamlResult<R>`
495    ///
496    /// If this is [`DamlValue`] is a [`DamlValue::Record`] then the extractor function is applied, otherwise an
497    /// [`DamlError::UnexpectedType`] error is returned.
498    ///
499    /// The extractor function can perform any arbitrary operation on the [`DamlRecord`] to produce an output value of
500    /// any reference type or an error.  The intent is to provide a function which can extract data from the
501    /// [`DamlRecord`] and any nested [`DamlValue`].
502    ///
503    /// This method is designed to be used with the `daml_path!` macro from the `daml-macro` crate which
504    /// provides a concise DSL for constructing a Daml data extractor closure.
505    ///
506    /// # Examples
507    ///
508    /// ```
509    /// # use daml_grpc::data::value::{DamlRecord, DamlValue, DamlRecordField};
510    /// # use daml_grpc::data::{DamlResult, DamlError};
511    /// # use daml_grpc::data::DamlIdentifier;
512    /// # use daml_grpc::primitive_types::{DamlParty, DamlText};
513    /// # fn main() -> DamlResult<()> {
514    /// let fields: Vec<DamlRecordField> = vec![DamlRecordField::new(Some("party"), DamlValue::new_party("Alice"))];
515    /// let record: DamlRecord = DamlRecord::new(fields, None::<DamlIdentifier>);
516    /// let record_value: DamlValue = DamlValue::new_record(record);
517    /// let text_value: DamlValue = DamlValue::new_text("test");
518    ///
519    /// fn my_party_extractor(rec: &DamlRecord) -> DamlResult<&DamlParty> {
520    ///     rec.field("party")?.try_party()
521    /// }
522    ///
523    /// fn my_text_extractor(rec: &DamlRecord) -> DamlResult<&DamlText> {
524    ///     rec.field("party")?.try_text()
525    /// }
526    ///
527    /// assert_eq!("Alice", record_value.extract(my_party_extractor)?);
528    /// assert_eq!(true, record_value.extract(my_text_extractor).is_err());
529    /// assert_eq!(true, text_value.extract(my_party_extractor).is_err());
530    /// # Ok(())
531    /// # }
532    /// ```
533    pub fn extract<'a, R, F>(&'a self, f: F) -> DamlResult<R>
534    where
535        F: FnOnce(&'a DamlRecord) -> DamlResult<R>,
536    {
537        f(self.try_record()?)
538    }
539
540    fn make_unexpected_type_error(&self, expected: &str) -> DamlError {
541        DamlError::UnexpectedType(expected.to_owned(), self.variant_name().to_owned())
542    }
543}
544
545impl From<()> for DamlValue {
546    fn from(_: ()) -> Self {
547        Self::new_unit()
548    }
549}
550
551impl From<bool> for DamlValue {
552    fn from(b: bool) -> Self {
553        Self::new_bool(b)
554    }
555}
556
557impl From<&str> for DamlValue {
558    fn from(s: &str) -> Self {
559        Self::new_text(s)
560    }
561}
562
563impl From<String> for DamlValue {
564    fn from(s: String) -> Self {
565        Self::new_text(s)
566    }
567}
568
569impl From<u8> for DamlValue {
570    fn from(i: u8) -> Self {
571        Self::new_int64(i)
572    }
573}
574
575impl From<i8> for DamlValue {
576    fn from(i: i8) -> Self {
577        Self::new_int64(i)
578    }
579}
580
581impl From<u16> for DamlValue {
582    fn from(i: u16) -> Self {
583        Self::new_int64(i)
584    }
585}
586
587impl From<i16> for DamlValue {
588    fn from(i: i16) -> Self {
589        Self::new_int64(i)
590    }
591}
592
593impl From<u32> for DamlValue {
594    fn from(i: u32) -> Self {
595        Self::new_int64(i)
596    }
597}
598
599impl From<i32> for DamlValue {
600    fn from(i: i32) -> Self {
601        Self::new_int64(i)
602    }
603}
604
605impl From<i64> for DamlValue {
606    fn from(i: i64) -> Self {
607        Self::new_int64(i)
608    }
609}
610impl TryFrom<f32> for DamlValue {
611    type Error = DamlError;
612
613    fn try_from(d: f32) -> DamlResult<Self> {
614        Ok(Self::new_numeric(DamlNumeric::try_from(d)?))
615    }
616}
617impl TryFrom<f64> for DamlValue {
618    type Error = DamlError;
619
620    fn try_from(d: f64) -> DamlResult<Self> {
621        Ok(Self::new_numeric(DamlNumeric::try_from(d)?))
622    }
623}
624
625impl DamlSerializeFrom<DamlUnit> for DamlValue {
626    fn serialize_from(_: DamlUnit) -> DamlValue {
627        Self::new_unit()
628    }
629}
630
631impl DamlSerializeFrom<DamlBool> for DamlValue {
632    fn serialize_from(b: DamlBool) -> DamlValue {
633        Self::new_bool(b)
634    }
635}
636
637impl DamlSerializeFrom<DamlInt64> for DamlValue {
638    fn serialize_from(i: DamlInt64) -> DamlValue {
639        Self::new_int64(i)
640    }
641}
642
643impl DamlSerializeFrom<DamlText> for DamlValue {
644    fn serialize_from(text: DamlText) -> DamlValue {
645        Self::new_text(text)
646    }
647}
648
649impl DamlSerializeFrom<DamlParty> for DamlValue {
650    fn serialize_from(party: DamlParty) -> DamlValue {
651        Self::new_party(party.party)
652    }
653}
654
655impl DamlSerializeFrom<DamlContractId> for DamlValue {
656    fn serialize_from(contract_id: DamlContractId) -> DamlValue {
657        Self::new_contract_id(contract_id.contract_id)
658    }
659}
660
661impl<T> DamlSerializeFrom<DamlFixedNumeric<T>> for DamlValue
662where
663    T: DamlSerializableType + Nat,
664{
665    fn serialize_from(numeric: DamlFixedNumeric<T>) -> DamlValue {
666        Self::new_numeric(numeric.value)
667    }
668}
669
670impl DamlSerializeFrom<DamlTimestamp> for DamlValue {
671    fn serialize_from(timestamp: DamlTimestamp) -> DamlValue {
672        Self::new_timestamp(timestamp)
673    }
674}
675
676impl DamlSerializeFrom<DamlDate> for DamlValue {
677    fn serialize_from(date: DamlDate) -> DamlValue {
678        Self::new_date(date)
679    }
680}
681
682impl<T> DamlSerializeFrom<Box<T>> for DamlValue
683where
684    T: DamlSerializableType + DamlSerializeInto<DamlValue>,
685{
686    fn serialize_from(boxed: Box<T>) -> DamlValue {
687        T::serialize_into(*boxed)
688    }
689}
690
691impl<T> DamlSerializeFrom<DamlOptional<T>> for DamlValue
692where
693    T: DamlSerializableType + DamlSerializeInto<DamlValue>,
694{
695    fn serialize_from(optional: DamlOptional<T>) -> DamlValue {
696        DamlValue::new_optional(optional.map(T::serialize_into))
697    }
698}
699
700impl<T> DamlSerializeFrom<DamlList<T>> for DamlValue
701where
702    T: DamlSerializableType + DamlSerializeInto<DamlValue>,
703{
704    fn serialize_from(list: DamlList<T>) -> DamlValue {
705        DamlValue::new_list(list.into_iter().map(T::serialize_into).collect::<DamlList<_>>())
706    }
707}
708
709impl<K, V> DamlSerializeFrom<DamlGenMap<K, V>> for DamlValue
710where
711    K: DamlSerializableType + DamlSerializeInto<DamlValue>,
712    V: DamlSerializableType + DamlSerializeInto<DamlValue>,
713{
714    fn serialize_from(gen_map: DamlGenMap<K, V>) -> DamlValue {
715        DamlValue::new_genmap(
716            gen_map
717                .into_iter()
718                .map(|(k, v)| (K::serialize_into(k), V::serialize_into(v)))
719                .collect::<DamlGenMap<_, _>>(),
720        )
721    }
722}
723
724impl<V> DamlSerializeFrom<DamlTextMap<V>> for DamlValue
725where
726    V: DamlSerializableType + DamlSerializeInto<DamlValue>,
727{
728    fn serialize_from(text_map: DamlTextMap<V>) -> DamlValue {
729        DamlValue::new_map(text_map.0.into_iter().map(|(k, v)| (k, V::serialize_into(v))).collect::<DamlTextMap<_>>())
730    }
731}
732
733impl DamlDeserializeFrom for DamlUnit {
734    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
735        match value {
736            DamlValue::Unit => Ok(()),
737            _ => Err(value.make_unexpected_type_error("Unit")),
738        }
739    }
740}
741
742impl DamlDeserializeFrom for DamlBool {
743    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
744        match value {
745            DamlValue::Bool(b) => Ok(b),
746            _ => Err(value.make_unexpected_type_error("Bool")),
747        }
748    }
749}
750
751impl DamlDeserializeFrom for DamlInt64 {
752    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
753        match value {
754            DamlValue::Int64(i) => Ok(i),
755            _ => Err(value.make_unexpected_type_error("Int64")),
756        }
757    }
758}
759
760impl DamlDeserializeFrom for DamlText {
761    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
762        match value {
763            DamlValue::Text(s) => Ok(s),
764            _ => Err(value.make_unexpected_type_error("Text")),
765        }
766    }
767}
768
769impl DamlDeserializeFrom for DamlParty {
770    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
771        match value {
772            DamlValue::Party(party) => Ok(party),
773            _ => Err(value.make_unexpected_type_error("Party")),
774        }
775    }
776}
777
778impl DamlDeserializeFrom for DamlContractId {
779    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
780        match value {
781            DamlValue::ContractId(contract_id) => Ok(contract_id),
782            _ => Err(value.make_unexpected_type_error("ContractId")),
783        }
784    }
785}
786
787impl<T> DamlDeserializeFrom for DamlFixedNumeric<T>
788where
789    T: DamlDeserializableType + Nat,
790{
791    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
792        match value {
793            DamlValue::Numeric(numeric) => Ok(DamlFixedNumeric::new(numeric)),
794            _ => Err(value.make_unexpected_type_error("Numeric")),
795        }
796    }
797}
798
799impl DamlDeserializeFrom for DamlTimestamp {
800    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
801        match value {
802            DamlValue::Timestamp(timestamp) => Ok(timestamp),
803            _ => Err(value.make_unexpected_type_error("Timestamp")),
804        }
805    }
806}
807
808impl DamlDeserializeFrom for DamlDate {
809    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
810        match value {
811            DamlValue::Date(date) => Ok(date),
812            _ => Err(value.make_unexpected_type_error("Date")),
813        }
814    }
815}
816
817impl<T> DamlDeserializeFrom for Box<T>
818where
819    T: DamlDeserializeFrom + DamlDeserializableType,
820{
821    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
822        Ok(Box::new(value.deserialize_into()?))
823    }
824}
825
826impl<T> DamlDeserializeFrom for DamlOptional<T>
827where
828    T: DamlDeserializeFrom + DamlDeserializableType,
829{
830    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
831        match value {
832            DamlValue::Optional(o) => Ok(o.map(|a| T::deserialize_from(*a)).transpose()?),
833            _ => Err(value.make_unexpected_type_error("Option")),
834        }
835    }
836}
837
838impl<T> DamlDeserializeFrom for DamlList<T>
839where
840    T: DamlDeserializeFrom + DamlDeserializableType,
841{
842    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
843        match value {
844            DamlValue::List(l) => Ok(l.into_iter().map(T::deserialize_from).collect::<DamlResult<DamlList<_>>>()?),
845            _ => Err(value.make_unexpected_type_error("List")),
846        }
847    }
848}
849
850impl<V> DamlDeserializeFrom for DamlTextMap<V>
851where
852    V: DamlDeserializeFrom + DamlDeserializableType,
853{
854    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
855        match value {
856            DamlValue::Map(text_map) => Ok(text_map
857                .into_iter()
858                .map(|(k, v)| Ok((k, V::deserialize_from(v)?)))
859                .collect::<DamlResult<DamlTextMap<_>>>()?),
860            _ => Err(value.make_unexpected_type_error("Map")),
861        }
862    }
863}
864
865impl<K, V> DamlDeserializeFrom for DamlGenMap<K, V>
866where
867    K: DamlDeserializeFrom + DamlDeserializableType + Ord,
868    V: DamlDeserializeFrom + DamlDeserializableType,
869{
870    fn deserialize_from(value: DamlValue) -> DamlResult<Self> {
871        match value {
872            DamlValue::GenMap(gen_map) => Ok(gen_map
873                .into_iter()
874                .map(|(k, v)| Ok((K::deserialize_from(k)?, V::deserialize_from(v)?)))
875                .collect::<DamlResult<DamlGenMap<_, _>>>()?),
876            _ => Err(value.make_unexpected_type_error("GenMap")),
877        }
878    }
879}
880
881impl TryFrom<Value> for DamlValue {
882    type Error = DamlError;
883
884    fn try_from(value: Value) -> Result<Self, Self::Error> {
885        Ok(match value.sum.req()? {
886            Sum::Record(v) => DamlValue::Record(v.try_into()?),
887            Sum::Variant(v) => DamlValue::Variant((*v).try_into()?),
888            Sum::Enum(e) => DamlValue::Enum(e.into()),
889            Sum::ContractId(v) => DamlValue::ContractId(DamlContractId::new(v)),
890            Sum::List(v) =>
891                DamlValue::List(v.elements.into_iter().map(TryInto::try_into).collect::<DamlResult<DamlList<_>>>()?),
892            Sum::Int64(v) => DamlValue::Int64(v),
893            Sum::Numeric(v) => DamlValue::Numeric(DamlNumeric::from_str(&v)?),
894            Sum::Text(v) => DamlValue::Text(v),
895            Sum::Timestamp(v) => DamlValue::Timestamp(util::datetime_from_micros(v)?),
896            Sum::Party(v) => DamlValue::Party(DamlParty::new(v)),
897            Sum::Bool(v) => DamlValue::Bool(v),
898            Sum::Unit(_) => DamlValue::Unit,
899            Sum::Date(v) => DamlValue::Date(util::date_from_days(v)?),
900            Sum::Optional(v) =>
901                DamlValue::Optional(v.value.map(|v| DamlValue::try_from(*v)).transpose()?.map(Box::new)),
902            Sum::Map(v) => DamlValue::Map(
903                v.entries
904                    .into_iter()
905                    .map(|v| Ok((v.key, v.value.req().and_then(DamlValue::try_from)?)))
906                    .collect::<DamlResult<DamlTextMap<_>>>()?,
907            ),
908            Sum::GenMap(v) => DamlValue::GenMap(
909                v.entries
910                    .into_iter()
911                    .map(|v| {
912                        Ok((v.key.req().and_then(DamlValue::try_from)?, v.value.req().and_then(DamlValue::try_from)?))
913                    })
914                    .collect::<DamlResult<DamlGenMap<_, _>>>()?,
915            ),
916        })
917    }
918}
919
920impl From<DamlValue> for Value {
921    fn from(daml_value: DamlValue) -> Self {
922        Self {
923            sum: match daml_value {
924                DamlValue::Record(v) => Some(Sum::Record(Record::from(v))),
925                DamlValue::Variant(v) => Some(Sum::Variant(Box::new(Variant::from(v)))),
926                DamlValue::Enum(e) => Some(Sum::Enum(Enum::from(e))),
927                DamlValue::ContractId(v) => Some(Sum::ContractId(v.contract_id)),
928                DamlValue::List(v) => Some(Sum::List(List {
929                    elements: v.into_iter().map(Value::from).collect(),
930                })),
931                DamlValue::Int64(v) => Some(Sum::Int64(v)),
932                // TODO: review the soundness of the numeric formatting here and consider using the `rust-decimal` crate
933                DamlValue::Numeric(v) => Some(Sum::Numeric(format!("{:.37}", v))),
934                DamlValue::Text(v) => Some(Sum::Text(v)), // value.set_text(v),
935                DamlValue::Timestamp(v) => Some(Sum::Timestamp(v.timestamp())),
936                DamlValue::Party(v) => Some(Sum::Party(v.party)),
937                DamlValue::Bool(v) => Some(Sum::Bool(v)),
938                DamlValue::Unit => Some(Sum::Unit(())),
939                DamlValue::Date(v) => Some(Sum::Date(util::days_from_date(v))),
940                DamlValue::Optional(Some(v)) => Some(Sum::Optional(Box::new(Optional {
941                    value: Some(Box::new(Value::from(*v))),
942                }))),
943                DamlValue::Optional(None) => Some(Sum::Optional(Box::new(Optional {
944                    value: None,
945                }))),
946                DamlValue::Map(v) => Some(Sum::Map(Map {
947                    entries: v
948                        .into_iter()
949                        .map(|(key, val)| map::Entry {
950                            key,
951                            value: Some(val.into()),
952                        })
953                        .collect(),
954                })),
955                DamlValue::GenMap(v) => Some(Sum::GenMap(GenMap {
956                    entries: v
957                        .into_iter()
958                        .map(|(key, val)| gen_map::Entry {
959                            key: Some(key.into()),
960                            value: Some(val.into()),
961                        })
962                        .collect(),
963                })),
964            },
965        }
966    }
967}
968
969/// A custom `PartialEq` implementation to allow us to order all possible `DamlValue` types.
970///
971/// This is required tp support the custom `Hash` implementation.
972impl PartialOrd for DamlValue {
973    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
974        match (self, other) {
975            (DamlValue::Record(v1), DamlValue::Record(v2)) => v1.partial_cmp(v2),
976            (DamlValue::Variant(v1), DamlValue::Variant(v2)) => v1.partial_cmp(v2),
977            (DamlValue::Enum(v1), DamlValue::Enum(v2)) => v1.partial_cmp(v2),
978            (DamlValue::List(v1), DamlValue::List(v2)) => v1.partial_cmp(v2.as_ref()),
979            (DamlValue::Int64(v1), DamlValue::Int64(v2)) => v1.partial_cmp(v2),
980            (DamlValue::Numeric(v1), DamlValue::Numeric(v2)) => v1.partial_cmp(v2),
981            (DamlValue::Text(v1), DamlValue::Text(v2)) => v1.partial_cmp(v2),
982            (DamlValue::Party(v1), DamlValue::Party(v2)) => v1.party.partial_cmp(&v2.party),
983            (DamlValue::ContractId(v1), DamlValue::ContractId(v2)) => v1.contract_id.partial_cmp(&v2.contract_id),
984            (DamlValue::Timestamp(v1), DamlValue::Timestamp(v2)) => v1.partial_cmp(v2),
985            (DamlValue::Bool(v1), DamlValue::Bool(v2)) => v1.partial_cmp(v2),
986            (DamlValue::Unit, DamlValue::Unit) => Some(Ordering::Equal),
987            (DamlValue::Date(v1), DamlValue::Date(v2)) => v1.partial_cmp(v2),
988            (DamlValue::Optional(v1), DamlValue::Optional(v2)) => v1.partial_cmp(v2),
989            (DamlValue::Map(v1), DamlValue::Map(v2)) =>
990                if v1.len() == v2.len() {
991                    v1.keys().sorted().partial_cmp(v2.keys().sorted())
992                } else {
993                    v1.len().partial_cmp(&v2.len())
994                },
995            (DamlValue::GenMap(v1), DamlValue::GenMap(v2)) =>
996                if v1.len() == v2.len() {
997                    v1.keys().partial_cmp(v2.keys())
998                } else {
999                    v1.len().partial_cmp(&v2.len())
1000                },
1001            _ => None,
1002        }
1003    }
1004}
1005
1006impl Ord for DamlValue {
1007    fn cmp(&self, other: &Self) -> Ordering {
1008        self.partial_cmp(other).unwrap()
1009    }
1010}
1011
1012#[cfg(test)]
1013mod tests {
1014    use crate::data::value::DamlValue;
1015    use crate::primitive_types::{DamlGenMap, DamlTextMap};
1016    use std::cmp::Ordering;
1017
1018    #[test]
1019    fn test_eq_for_text() {
1020        let value1 = DamlValue::Text(String::from("text"));
1021        let value2 = DamlValue::Text(String::from("text"));
1022        assert_eq!(value1, value2);
1023    }
1024
1025    #[test]
1026    fn test_ord_for_text() {
1027        let value1 = DamlValue::Text(String::from("textA"));
1028        let value2 = DamlValue::Text(String::from("textB"));
1029        assert_eq!(value1.cmp(&value2), Ordering::Less);
1030    }
1031
1032    #[test]
1033    fn test_eq_for_i64() {
1034        let value1 = DamlValue::Int64(101);
1035        let value2 = DamlValue::Int64(101);
1036        assert_eq!(value1, value2);
1037    }
1038
1039    #[test]
1040    fn test_ord_for_i64() {
1041        let value1 = DamlValue::Int64(102);
1042        let value2 = DamlValue::Int64(101);
1043        assert_eq!(value1.cmp(&value2), Ordering::Greater);
1044    }
1045
1046    #[test]
1047    fn test_eq_for_textmap() {
1048        let items =
1049            vec![(String::from("text1"), DamlValue::Int64(100)), (String::from("text2"), DamlValue::Int64(200))];
1050        let value1 = DamlValue::Map(items.clone().into_iter().collect::<DamlTextMap<DamlValue>>());
1051        let value2 = DamlValue::Map(items.into_iter().collect::<DamlTextMap<DamlValue>>());
1052        assert_eq!(value1, value2);
1053    }
1054
1055    #[test]
1056    fn test_ord_for_textmap() {
1057        let items1 =
1058            vec![(String::from("text1"), DamlValue::Int64(100)), (String::from("text2"), DamlValue::Int64(200))];
1059        let items2 =
1060            vec![(String::from("text2"), DamlValue::Int64(100)), (String::from("text3"), DamlValue::Int64(200))];
1061        let items3 =
1062            vec![(String::from("text1"), DamlValue::Int64(100)), (String::from("text2"), DamlValue::Int64(200))];
1063        let value1 = DamlValue::Map(items1.into_iter().collect::<DamlTextMap<DamlValue>>());
1064        let value2 = DamlValue::Map(items2.into_iter().collect::<DamlTextMap<DamlValue>>());
1065        let value3 = DamlValue::Map(items3.into_iter().collect::<DamlTextMap<DamlValue>>());
1066        assert_eq!(value1.cmp(&value2), Ordering::Less);
1067        assert_eq!(value2.cmp(&value1), Ordering::Greater);
1068        assert_eq!(value1.cmp(&value3), Ordering::Equal);
1069    }
1070
1071    #[test]
1072    fn test_eq_for_genmap() {
1073        let items = vec![
1074            (DamlValue::Text(String::from("text1")), DamlValue::Int64(100)),
1075            (DamlValue::Text(String::from("text2")), DamlValue::Int64(200)),
1076        ];
1077        let value1 = DamlValue::GenMap(items.clone().into_iter().collect::<DamlGenMap<_, _>>());
1078        let value2 = DamlValue::GenMap(items.into_iter().collect::<DamlGenMap<_, _>>());
1079        assert_eq!(value1, value2);
1080    }
1081
1082    #[test]
1083    fn test_ord_for_genmap() {
1084        let items1 = vec![
1085            (DamlValue::Text(String::from("text1")), DamlValue::Int64(100)),
1086            (DamlValue::Text(String::from("text2")), DamlValue::Int64(200)),
1087        ];
1088        let items2 = vec![
1089            (DamlValue::Text(String::from("text2")), DamlValue::Int64(100)),
1090            (DamlValue::Text(String::from("text3")), DamlValue::Int64(200)),
1091        ];
1092        let items3 = vec![
1093            (DamlValue::Text(String::from("text1")), DamlValue::Int64(100)),
1094            (DamlValue::Text(String::from("text2")), DamlValue::Int64(200)),
1095        ];
1096        let value1 = DamlValue::GenMap(items1.into_iter().collect::<DamlGenMap<DamlValue, DamlValue>>());
1097        let value2 = DamlValue::GenMap(items2.into_iter().collect::<DamlGenMap<DamlValue, DamlValue>>());
1098        let value3 = DamlValue::GenMap(items3.into_iter().collect::<DamlGenMap<DamlValue, DamlValue>>());
1099        assert_eq!(value1.cmp(&value2), Ordering::Less);
1100        assert_eq!(value2.cmp(&value1), Ordering::Greater);
1101        assert_eq!(value1.cmp(&value3), Ordering::Equal);
1102    }
1103}