daml_grpc/data/value/
record.rs

1use crate::data::value::{DamlRecordField, DamlValue};
2use crate::data::{DamlError, DamlIdentifier, DamlResult};
3use crate::grpc_protobuf::com::daml::ledger::api::v1::{Identifier, Record, RecordField};
4use std::convert::{TryFrom, TryInto};
5
6/// A representation of the fields on a Daml `template` or `data` construct.
7#[derive(Debug, PartialEq, Eq, Default, Clone, Ord, PartialOrd)]
8pub struct DamlRecord {
9    record_id: Option<DamlIdentifier>,
10    fields: Vec<DamlRecordField>,
11}
12
13impl DamlRecord {
14    pub fn empty() -> Self {
15        Self {
16            record_id: None,
17            fields: vec![],
18        }
19    }
20
21    // TODO improve this to not need a type hint at the call site for None case
22    pub fn new(fields: impl Into<Vec<DamlRecordField>>, record_id: Option<impl Into<DamlIdentifier>>) -> Self {
23        Self {
24            record_id: record_id.map(Into::into),
25            fields: fields.into(),
26        }
27    }
28
29    pub const fn record_id(&self) -> &Option<DamlIdentifier> {
30        &self.record_id
31    }
32
33    pub const fn fields(&self) -> &Vec<DamlRecordField> {
34        &self.fields
35    }
36
37    pub fn field(&self, label: &str) -> DamlResult<&DamlValue> {
38        self.fields
39            .iter()
40            .find_map(|rec| match rec.label() {
41                Some(ll) if ll == label => Some(rec.value()),
42                _ => None,
43            })
44            .ok_or_else(|| DamlError::UnknownField(label.to_owned()))
45    }
46
47    /// Apply a Daml data extractor function.
48    ///
49    /// See [`DamlValue::extract`] for details an examples.
50    pub fn extract<'a, R, F>(&'a self, f: F) -> DamlResult<R>
51    where
52        F: Fn(&'a Self) -> DamlResult<R>,
53    {
54        f(self)
55    }
56}
57
58impl TryFrom<Record> for DamlRecord {
59    type Error = DamlError;
60
61    fn try_from(record: Record) -> Result<Self, Self::Error> {
62        let fields = record.fields.into_iter().map(TryInto::try_into).collect::<DamlResult<Vec<DamlRecordField>>>()?;
63        Ok(Self::new(fields, record.record_id.map(DamlIdentifier::from)))
64    }
65}
66
67impl From<DamlRecord> for Record {
68    fn from(daml_record: DamlRecord) -> Self {
69        Self {
70            record_id: daml_record.record_id.map(Identifier::from),
71            fields: daml_record.fields.into_iter().map(RecordField::from).collect(),
72        }
73    }
74}
75
76impl TryFrom<DamlValue> for DamlRecord {
77    type Error = DamlError;
78
79    fn try_from(value: DamlValue) -> Result<Self, Self::Error> {
80        value.try_take_record()
81    }
82}