1#[macro_export]
117macro_rules! daml_value {
118
119 () => {
123 DamlValue::Unit
124 };
125
126 ([ $( $value:tt $( :: $type:ident )? ),* ]) => {
130 {
131 use $crate::daml_grpc::data::value::DamlValue;
132 #[allow(unused_mut)]
133 let mut list = vec![];
134 $(
135 #[allow(clippy::vec_init_then_push)]
136 list.push(daml_value!($( @priv $type )? $value));
137 )*
138 DamlValue::List(list)
139 }
140 };
141
142 ( { $( $label:ident : $value:tt $( :: $type:ident )? ),* } ) => {
146 {
147 use $crate::daml_grpc::data::value::{DamlValue, DamlRecordBuilder};
148 #[allow(unused_mut)]
149 let mut rec_builder = DamlRecordBuilder::new();
150 $(
151 rec_builder = rec_builder.add_field(stringify![$label], daml_value!($( @priv $type )? $value));
152 )*
153 DamlValue::new_record(rec_builder.build())
154 }
155 };
156
157 ( { => $variant:ident $($value:tt)* } ) => {
161 {
162 use $crate::daml_grpc::data::value::{DamlValue, DamlVariant};
163 let val = daml_value!($($value)*);
164 let variant = DamlVariant::new(stringify!($variant), Box::new(val), None);
165 DamlValue::new_variant(variant)
166 }
167 };
168
169 ( { ?= $($value:tt)* } ) => {
173 {
174 use $crate::daml_grpc::data::value::DamlValue;
175 let val = daml_value!($($value)*);
176 DamlValue::new_optional(Some(val))
177 }
178 };
179
180 ( { ?! } ) => {
184 {
185 use $crate::daml_grpc::data::value::DamlValue;
186 DamlValue::new_optional(None)
187 }
188 };
189
190 ($prim:expr) => {
194 {
195 use std::convert::TryFrom;
196 $crate::daml_grpc::data::value::DamlValue::try_from($prim).expect("invalid numeric")
197 }
198 };
199
200 ($party:tt :: p) => {
204 daml_value!(@priv p $party)
205 };
206 ($contract:tt :: c) => {
207 daml_value!(@priv c $contract)
208 };
209 ($timestamp:tt :: t) => {
210 daml_value!(@priv t $timestamp)
211 };
212 ($date:tt :: d) => {
213 daml_value!(@priv d $date)
214 };
215
216 (@priv p $party:expr) => {
220 $crate::daml_grpc::data::value::DamlValue::new_party($party)
221 };
222 (@priv c $contract:expr) => {
223 $crate::daml_grpc::data::value::DamlValue::new_contract_id($contract)
224 };
225 (@priv t $timestamp:expr) => {
226 $crate::daml_grpc::data::value::DamlValue::new_timestamp($timestamp.parse::<$crate::chrono::DateTime<$crate::chrono::Utc>>().unwrap()) };
228 (@priv d $date:expr) => {
229 $crate::daml_grpc::data::value::DamlValue::new_date($crate::chrono::Date::<$crate::chrono::Utc>::from_utc($crate::chrono::NaiveDate::parse_from_str($date, "%Y-%m-%d").unwrap(), $crate::chrono::Utc))
231 };
232}
233
234#[cfg(test)]
235mod test {
236 use crate::test_util::TestResult;
237 use crate::test_util::{make_date, make_timestamp};
238 use bigdecimal::BigDecimal;
239 use daml_grpc::data::value::DamlValue;
240 use std::convert::TryFrom;
241
242 #[test]
243 pub fn test_unit_value() -> TestResult {
244 let value: DamlValue = daml_value![];
245 assert_eq!((), value.try_unit()?);
246 Ok(())
247 }
248
249 #[test]
250 pub fn test_string_value() -> TestResult {
251 let value: DamlValue = daml_value!["Test"];
252 assert_eq!("Test", value.try_text()?);
253 Ok(())
254 }
255
256 #[test]
257 pub fn test_party_value() -> TestResult {
258 let value: DamlValue = daml_value![DamlValue::new_party("Test")];
259 assert_eq!("Test", value.try_party()?);
260 Ok(())
261 }
262
263 #[test]
264 pub fn test_party_literal() -> TestResult {
265 let value: DamlValue = daml_value!["Test"::p];
266 assert_eq!("Test", value.try_party()?);
267 Ok(())
268 }
269
270 #[test]
271 pub fn test_contract_id_value() -> TestResult {
272 let value: DamlValue = daml_value![DamlValue::new_contract_id("123")];
273 assert_eq!("123", value.try_contract_id()?);
274 Ok(())
275 }
276
277 #[test]
278 pub fn test_contract_id_literal() -> TestResult {
279 let value: DamlValue = daml_value!["123"::c];
280 assert_eq!("123", value.try_contract_id()?);
281 Ok(())
282 }
283
284 #[test]
285 pub fn test_int64_value() -> TestResult {
286 let value: DamlValue = daml_value![42];
287 assert_eq!(42, value.try_int64()?);
288 Ok(())
289 }
290
291 #[test]
292 pub fn test_bool_value() -> TestResult {
293 let value: DamlValue = daml_value![true];
294 assert!(value.try_bool()?);
295 Ok(())
296 }
297
298 #[test]
299 pub fn test_numeric_value() -> TestResult {
300 let value: DamlValue = daml_value![1.23];
301 assert_eq!(&BigDecimal::try_from(1.23).unwrap(), value.try_numeric()?);
302 Ok(())
303 }
304
305 #[test]
306 pub fn test_timestamp_value() -> TestResult {
307 let value: DamlValue = daml_value!["2019-01-02T03:45:56Z"::t];
308 assert_eq!(make_timestamp("2019-01-02T03:45:56Z")?, value.try_timestamp()?);
309 Ok(())
310 }
311
312 #[test]
313 pub fn test_timestamp_literal() -> TestResult {
314 let timestamp = make_timestamp("2019-01-02T03:45:56Z")?;
315 let value: DamlValue = daml_value![DamlValue::new_timestamp(timestamp)];
316 assert_eq!(timestamp, value.try_timestamp()?);
317 Ok(())
318 }
319
320 #[test]
321 pub fn test_date_literal() -> TestResult {
322 let value: DamlValue = daml_value!["2019-01-02"::d];
323 assert_eq!(make_date("2019-01-02")?, value.try_date()?);
324 Ok(())
325 }
326
327 #[test]
328 pub fn test_date_value() -> TestResult {
329 let date = make_date("2019-01-02")?;
330 let value: DamlValue = daml_value![DamlValue::new_date(date)];
331 assert_eq!(date, value.try_date()?);
332 Ok(())
333 }
334
335 #[test]
336 pub fn test_empty_record() -> TestResult {
337 let value: DamlValue = daml_value![{}];
338 assert_eq!(0, value.try_record()?.fields().len());
339 Ok(())
340 }
341
342 #[test]
343 pub fn test_simple_record() -> TestResult {
344 let value: DamlValue = daml_value![{
345 sender: "Alice"::p,
346 receiver: "Bob"::p,
347 count: 0
348 }];
349 assert_eq!("Alice", value.try_record()?.fields()[0].value().try_party()?);
350 assert_eq!("Bob", value.try_record()?.fields()[1].value().try_party()?);
351 assert_eq!(0, value.try_record()?.fields()[2].value().try_int64()?);
352 Ok(())
353 }
354
355 #[test]
356 pub fn test_optional_none() -> TestResult {
357 let value: DamlValue = daml_value![{?!}];
358 assert_eq!(None, value.try_optional()?);
359 Ok(())
360 }
361
362 #[test]
363 pub fn test_optional_text() -> TestResult {
364 let value: DamlValue = daml_value![{?="bar"}];
365 assert_eq!("bar", value.try_optional()?.ok_or("not ok")?.try_text()?);
366 Ok(())
367 }
368
369 #[test]
370 pub fn test_optional_record() -> TestResult {
371 let value: DamlValue = daml_value![{?={
372 sender: "Alice"::p,
373 receiver: "Bob"::p,
374 count: 0
375 }}];
376 assert_eq!("Alice", value.try_optional()?.ok_or("not ok")?.try_record()?.fields()[0].value().try_party()?);
377 assert_eq!("Bob", value.try_optional()?.ok_or("not ok")?.try_record()?.fields()[1].value().try_party()?);
378 assert_eq!(0, value.try_optional()?.ok_or("not ok")?.try_record()?.fields()[2].value().try_int64()?);
379 Ok(())
380 }
381
382 #[test]
383 pub fn test_variant_text() -> TestResult {
384 let value: DamlValue = daml_value![{=>foo "bar"}];
385 assert_eq!("bar", value.try_variant()?.value().try_text()?);
386 assert_eq!("foo", value.try_variant()?.constructor());
387 Ok(())
388 }
389
390 #[test]
391 pub fn test_variant_party_literal() -> TestResult {
392 let value: DamlValue = daml_value![{=>PartyId "Bob"::p}];
393 assert_eq!("Bob", value.try_variant()?.value().try_party()?);
394 assert_eq!("PartyId", value.try_variant()?.constructor());
395 Ok(())
396 }
397
398 #[test]
399 pub fn test_variant_record() -> TestResult {
400 let value: DamlValue = daml_value![{=>Variant1 {
401 sender: "Alice"::p,
402 receiver: "Bob"::p,
403 count: 0
404 }}];
405 assert_eq!("Alice", value.try_variant()?.value().try_record()?.fields()[0].value().try_party()?);
406 assert_eq!("Bob", value.try_variant()?.value().try_record()?.fields()[1].value().try_party()?);
407 assert_eq!(0, value.try_variant()?.value().try_record()?.fields()[2].value().try_int64()?);
408 assert_eq!("Variant1", value.try_variant()?.constructor());
409 Ok(())
410 }
411
412 #[test]
413 pub fn test_nested_variant() -> TestResult {
414 let value: DamlValue = daml_value![{
415 data: {=>SomeVariant "data from SomeVariant"}
416 }];
417 assert_eq!("data from SomeVariant", value.try_record()?.fields()[0].value().try_variant()?.value().try_text()?);
418 assert_eq!("SomeVariant", value.try_record()?.fields()[0].value().try_variant()?.constructor());
419 Ok(())
420 }
421
422 #[test]
423 pub fn test_nested_variant_record() -> TestResult {
424 let value: DamlValue = daml_value![{
425 data: {=>foo {a: "test"}}
426 }];
427 assert_eq!(
428 "test",
429 value.try_record()?.fields()[0].value().try_variant()?.value().try_record()?.fields()[0]
430 .value()
431 .try_text()?
432 );
433 Ok(())
434 }
435
436 #[test]
437 pub fn test_nested_variant_record_optional() -> TestResult {
438 let value: DamlValue = daml_value![{
439 sender: "Alice"::p,
440 receiver: "Bob"::p,
441 count: 0,
442 data: {=>foo {
443 mand_text: "test",
444 opt_int: {?= 0},
445 opt_node: {?!}
446 }}
447 }];
448 assert_eq!(
449 "test",
450 value.try_record()?.fields()[3].value().try_variant()?.value().try_record()?.fields()[0]
451 .value()
452 .try_text()?
453 );
454 assert_eq!(
455 0,
456 value.try_record()?.fields()[3].value().try_variant()?.value().try_record()?.fields()[1]
457 .value()
458 .try_optional()?
459 .ok_or("not ok")?
460 .try_int64()?
461 );
462 assert_eq!(
463 None,
464 value.try_record()?.fields()[3].value().try_variant()?.value().try_record()?.fields()[2]
465 .value()
466 .try_optional()?
467 );
468 Ok(())
469 }
470
471 #[test]
472 pub fn test_nested_record() -> TestResult {
473 let value: DamlValue = daml_value![{
474 sender: "Alice"::p,
475 receiver: "Bob"::p,
476 data: {
477 count: 0,
478 fruit: "apple",
479 contractId: "#1:1"::c
480 }
481 }];
482 assert_eq!("Alice", value.try_record()?.fields()[0].value().try_party()?);
483 assert_eq!("Bob", value.try_record()?.fields()[1].value().try_party()?);
484 assert_eq!(0, value.try_record()?.fields()[2].value().try_record()?.fields()[0].value().try_int64()?);
485 assert_eq!("apple", value.try_record()?.fields()[2].value().try_record()?.fields()[1].value().try_text()?);
486 assert_eq!(
487 "#1:1",
488 value.try_record()?.fields()[2].value().try_record()?.fields()[2].value().try_contract_id()?
489 );
490 Ok(())
491 }
492
493 #[test]
494 pub fn test_empty_list() -> TestResult {
495 let value: DamlValue = daml_value!([]);
496 assert_eq!(0, value.try_list()?.len());
497 Ok(())
498 }
499
500 #[test]
501 pub fn test_simple_list() -> TestResult {
502 let value: DamlValue = daml_value!([1, 2, 3]);
503 assert_eq!(1, value.try_list()?[0].try_int64()?);
504 assert_eq!(3, value.try_list()?.len());
505 Ok(())
506 }
507
508 #[test]
509 pub fn test_list_of_empty_records() -> TestResult {
510 let value: DamlValue = daml_value!([{}, {}]);
511 assert_eq!(2, value.try_list()?.len());
512 assert_eq!(0, value.try_list()?[1].try_record()?.fields().len());
513 Ok(())
514 }
515
516 #[test]
517 pub fn test_list_of_record() -> TestResult {
518 let value: DamlValue = daml_value!(
519 [{
520 foo: "bar",
521 bar: "foo"
522 }]
523 );
524 assert_eq!(1, value.try_list()?.len());
525 assert_eq!("foo", value.try_list()?[0].try_record()?.fields()[1].value().try_text()?);
526 Ok(())
527 }
528
529 #[test]
530 pub fn test_list_of_mixed() -> TestResult {
531 let value: DamlValue = daml_value!(
532 [{
533 foo: "bar",
534 bar: "foo"
535 },
536 "Bob"::p,
537 10
538 ]
539 );
540 assert_eq!(3, value.try_list()?.len());
541 assert_eq!("foo", value.try_list()?[0].try_record()?.fields()[1].value().try_text()?);
542 assert_eq!("Bob", value.try_list()?[1].try_party()?);
543 assert_eq!(10, value.try_list()?[2].try_int64()?);
544 Ok(())
545 }
546
547 #[test]
548 pub fn test_expressions() -> TestResult {
549 let value: DamlValue = daml_value![{
550 name: (String::from("John")),
551 age: (21 + 3)
552 }];
553 assert_eq!("John", value.try_record()?.fields()[0].value().try_text()?);
554 assert_eq!(24, value.try_record()?.fields()[1].value().try_int64()?);
555 Ok(())
556 }
557
558 #[test]
559 pub fn test_from_variables() -> TestResult {
560 let party = "John";
561 let age = 21;
562 let dob = "1999-12-31";
563 let home_address = "somewhere";
564 let value: DamlValue = daml_value![{
565 party: party::p,
566 age: age,
567 dob: dob::d,
568 sex: "Male",
569 address: home_address
570 }];
571 assert_eq!("John", value.try_record()?.fields()[0].value().try_party()?);
572 assert_eq!(21, value.try_record()?.fields()[1].value().try_int64()?);
573 assert_eq!(make_date("1999-12-31")?, value.try_record()?.fields()[2].value().try_date()?);
574 assert_eq!("Male", value.try_record()?.fields()[3].value().try_text()?);
575 assert_eq!("somewhere", value.try_record()?.fields()[4].value().try_text()?);
576 Ok(())
577 }
578}