macro_rules! daml_path {
( @priv $record:ident / $path:ident $( { => $variant:ident } )? [ $index:expr ] ? $( :: $type:ident )? ) => { ... };
( @priv $record:ident / $path:ident $( { => $variant:ident } )? [ $index:expr ] $( :: $type:ident )? ) => { ... };
( @priv $record:ident / $path:ident $( { => $variant:ident } )? $( :: $type:ident )? ) => { ... };
( @priv $record:ident / $path:ident $( { => $variant:ident } )? ? $( :: $type:ident )? ) => { ... };
( @priv $record:ident / $path:ident $( { => $variant:ident } )? [ $index:expr ] ? $($rest:tt)* ) => { ... };
( @priv $record:ident / $path:ident $( { => $variant:ident } )? [ $index:expr ] $($rest:tt)* ) => { ... };
( @priv $record:ident / $path:ident $( { => $variant:ident } )? ? $($rest:tt)* ) => { ... };
( @priv $record:ident / $path:ident { => $variant:ident } $($rest0:tt)* ) => { ... };
( @priv $record:ident / $path:ident $( { => $variant:ident } )? $($rest1:tt)* ) => { ... };
( @priv $value:ident ) => { ... };
( @priv c $value:ident ) => { ... };
( @priv u $value:ident ) => { ... };
( @priv p $value:ident ) => { ... };
( @priv i $value:ident ) => { ... };
( @priv f $value:ident ) => { ... };
( @priv t $value:ident ) => { ... };
( @priv b $value:ident ) => { ... };
( @priv s $value:ident ) => { ... };
( @priv d $value:ident ) => { ... };
( @priv r $value:ident ) => { ... };
( @priv l $value:ident ) => { ... };
( @priv v $value:ident ) => { ... };
( @get_record_field $record:ident, $path:ident ) => { ... };
( @get_list_item $value:ident, $index:expr ) => { ... };
( @get_variant_value $value:ident , $variant:ident ) => { ... };
( @get_variant_value $value:ident , ) => { ... };
( $($rest:tt)* ) => { ... };
}
Expand description
Construct a Daml data extractor function from a path expression.
This macro provides a concise DSL for constructing a Daml data extractor closure as required by
DamlRecord::extract
and DamlValue::extract
. The closure produced will have the following signature:
Fn(&DamlRecord) -> DamlResult<R>
The type of R
depends on the path expression provided and may either be a reference to a DamlValue
or a
reference to another type such as &str
.
§Syntax
Path expressions take the following form (pseudo-regex syntax):
field ( '{' '=>' variant '}' )? ( '[' index ']' )? ( '?' )? ( '/' ... )* ( '::' type )?
----- ------------------------- ------------------ -------- - --- --- -- --------------
(1) (2) (3) (4) | (5) (6) | (7)
Each field
corresponds to a labelled DamlRecordField
within the DamlRecord
on which the data extractor
is to be executed.
Syntax Items:
- the
field
of the currentDamlValue::Record
to traverse - extract the
DamlValue
iffield
is aDamlValue::Variant
andvariant
matches the constructor. - extract the
DamlValue
from list atindex
(expression) iffield
is aDamlValue::List
- extract the
DamlValue
iffield
is aDamlValue::Optional
- a separator between
field
entries - a repeat of items
(1)
,(2)
,(3)
&(4)
. Items(5)
&(6)
are repeated zero or many times. - an optional type specifier
Note that any or all of (2)
, (3)
& (4)
can be applied for a single field
and will run consecutively. i.e.
in the single path field people{=>Persons}[0]?
will interpret people
as a DamlValue::Variant
with a
constructor of Persons
which is a DamlValue::List
which has an element at index 0
which contain an
DamlValue::Optional
that is a DamlValue::Int64
.
Note that the path expression is not whitespace sensitive.
Fields which are nested DamlRecord
can be traversed by chaining together multiple field
elements delimited
with a /
character. Nesting can be of arbitrary depth (up to the default recursive macro limit). Attempting
to access a non-existent field will return in an UnknownField
error being returned.
List elements of fields
which are of type DamlValue::List
can be accessed by specifying a list index
expression inside []
braces. A ListIndexOutOfRange
error will be returned if an attempt is made to access
lists elements outside the available bounds.
Optional fields
of type DamlValue::Optional
can be accessed by appending a ?
character to the record
field
name or list element. If the optional is Some
then the embedded DamlValue
is extracted and
processing of the path expression continues. If the optional is None
then a MissingRequiredField
error
will be returned.
The final field
may optionally have a type
specifier by appending a ::
token followed by one
of several supported type
specifier codes. If no type
specifier code is provided then the expression will
return a DamlValue
otherwise a type appropriate to the specifier will be returned.
If the constructor of a DamlValue::Variant
does not match then UnexpectedVariant
error is returned. The
special variant value of __
can be used to indicate that any variant is acceptable. Attempting to access the
nested DamlValue
within a variant will produce an error if the type of the item does not match the actual
variant type.
The supported type
specifiers are:
code | name | Rust type | value variant |
---|---|---|---|
c | contract id | &str | DamlValue::ContractId |
u | unit | &() | DamlValue::Unit |
p | party | &str | DamlValue::Party |
i | int64 | &i64 | DamlValue::Int64 |
f | numeric | &BigInteger | DamlValue::Numeric |
t | text | &str | DamlValue::Text |
s | timestamp | &DateTime<Utc> | DamlValue::Timestamp |
b | boolean | &bool | DamlValue::Bool |
d | date | &Date<Utc> | DamlValue::Date |
r | record | &DamlRecord | DamlValue::Record |
l | list | &Vec<DamlValue> | DamlValue::List |
v | variant | &DamlVariant | DamlValue::Variant |
§Limitations
Path expressions only support labelled DamlRecordField
fields. Accessing unlabelled fields will result in
an UnknownField
error being returned.
Accessing values from a list-of-list is not supported and therefore path expression syntax my_list[0][1]
is not
valid. To access the sublist first extract the parent list with the path expression my_list[0]
and then apply a
second path expression to the resulting DamlValue
. Note that a list containing DamlRecord
which in turn
contains nested lists is supported.
All type
specifiers return references, even for simple copy types, and so must be dereferenced as needed.
There is currently no support for DamlValue::Map
, DamlValue::GenMap
or DamlValue::Enum
.
§Examples
let value = daml_value![{
party: "Alice"::p,
trade: {
trade_id: 123,
counterparty: "Bob"::p,
trade_details: {
ticker: "GOOG",
prices: [1231.54, 1234.85, 1237.92]
},
order_type: {?= "MarketOrder"}
}
}];
assert_eq!("Alice", value.extract(daml_path![party::p])?);
assert_eq!(123, *value.extract(daml_path![trade/trade_id::i])?);
assert_eq!("Bob", value.extract(daml_path![trade/counterparty::p])?);
assert_eq!("GOOG", value.extract(daml_path![trade/trade_details/ticker::t])?);
assert_eq!(&BigDecimal::try_from(1234.85).unwrap(),
value.extract(daml_path![trade/trade_details/prices[1]::f])?);
assert_eq!("MarketOrder", value.extract(daml_path![trade/order_type?::t])?);