1use std::borrow::Cow;
2
3use serde::Serialize;
4
5use crate::element::visitor::DamlElementVisitor;
6use crate::element::{DamlData, DamlField, DamlTypeVarWithKind, DamlVisitableElement};
7use bounded_static::ToStatic;
8use std::fmt;
9use std::fmt::{Display, Formatter};
10use std::hash::{Hash, Hasher};
11
12#[derive(Debug, Serialize, Clone, ToStatic)]
14pub enum DamlType<'a> {
15 ContractId(Option<Box<DamlType<'a>>>),
17 Int64,
19 Numeric(Vec<DamlType<'a>>),
21 Text,
23 Timestamp,
25 Party,
27 Bool,
29 Unit,
31 Date,
33 List(Vec<DamlType<'a>>),
35 TextMap(Vec<DamlType<'a>>),
37 GenMap(Vec<DamlType<'a>>),
39 Optional(Vec<DamlType<'a>>),
41 TyCon(DamlTyCon<'a>),
43 BoxedTyCon(DamlTyCon<'a>),
45 Var(DamlVar<'a>),
47 Nat(u8),
49 Arrow,
51 Any,
53 TypeRep,
55 Bignumeric,
57 RoundingMode,
59 AnyException,
61 Update,
63 Scenario,
65 Forall(DamlForall<'a>),
67 Struct(DamlStruct<'a>),
69 Syn(DamlSyn<'a>),
71}
72
73impl<'a> DamlType<'a> {
74 pub fn name(&self) -> &str {
75 match self {
76 DamlType::ContractId(_) => "DamlContractId",
77 DamlType::Int64 => "DamlInt64",
78 DamlType::Numeric(_) => "DamlFixedNumeric",
79 DamlType::Text => "DamlText",
80 DamlType::Timestamp => "DamlTimestamp",
81 DamlType::Party => "DamlParty",
82 DamlType::Bool => "DamlBool",
83 DamlType::Unit => "DamlUnit",
84 DamlType::Date => "DamlDate",
85 DamlType::List(_) => "DamlList",
86 DamlType::TextMap(_) => "DamlTextMap",
87 DamlType::GenMap(_) => "DamlGenMap",
88 DamlType::Optional(_) => "DamlOptional",
89 DamlType::Update => "None (Update)",
90 DamlType::Scenario => "None (Scenario)",
91 DamlType::TyCon(_) => "None (TyCon)",
92 DamlType::BoxedTyCon(_) => "None (BoxedTyCon)",
93 DamlType::Var(_) => "None (Var)",
94 DamlType::Arrow => "None (Arrow)",
95 DamlType::Any => "None (Any)",
96 DamlType::TypeRep => "None (TypeRep)",
97 DamlType::RoundingMode => "None (RoundingMode)",
98 DamlType::AnyException => "None (AnyException)",
99 DamlType::Bignumeric => "None (Bignumeric)",
100 DamlType::Nat(_) => "Nat",
101 DamlType::Forall(_) => "Forall",
102 DamlType::Struct(_) => "Struct",
103 DamlType::Syn(_) => "Syn",
104 }
105 }
106
107 pub fn contains_type_var(&self, type_var: &str) -> bool {
109 match self {
110 DamlType::Var(DamlVar {
111 var,
112 ..
113 }) => var == type_var,
114 DamlType::List(args)
115 | DamlType::Optional(args)
116 | DamlType::TextMap(args)
117 | DamlType::GenMap(args)
118 | DamlType::Numeric(args) => args.iter().any(|arg| arg.contains_type_var(type_var)),
119 DamlType::ContractId(inner) => inner.as_ref().map_or(false, |ty| ty.contains_type_var(type_var)),
120 DamlType::TyCon(tycon) | DamlType::BoxedTyCon(tycon) =>
121 tycon.type_arguments.iter().any(|f| f.contains_type_var(type_var)),
122 DamlType::Forall(forall) => forall.body.as_ref().contains_type_var(type_var),
123 DamlType::Struct(tuple) => tuple.fields.iter().any(|field| field.ty().contains_type_var(type_var)),
124 DamlType::Syn(syn) => syn.args.iter().any(|arg| arg.contains_type_var(type_var)),
125 DamlType::Int64
126 | DamlType::Text
127 | DamlType::Timestamp
128 | DamlType::Party
129 | DamlType::Bool
130 | DamlType::Unit
131 | DamlType::Date
132 | DamlType::Update
133 | DamlType::Scenario
134 | DamlType::Arrow
135 | DamlType::Any
136 | DamlType::TypeRep
137 | DamlType::Bignumeric
138 | DamlType::RoundingMode
139 | DamlType::AnyException
140 | DamlType::Nat(_) => false,
141 }
142 }
143
144 pub fn make_tycon<'b, S: AsRef<str> + 'b>(package_id: &'b str, module: &'b [S], entity: &'b str) -> DamlType<'b> {
146 Self::make_tycon_with_args(package_id, module, entity, vec![])
147 }
148
149 pub fn make_tycon_with_args<'b, S: AsRef<str> + 'b>(
151 package_id: &'b str,
152 module: &'b [S],
153 entity: &'b str,
154 type_arguments: Vec<DamlType<'b>>,
155 ) -> DamlType<'b> {
156 DamlType::TyCon(DamlTyCon::new_absolute_with_type_args(package_id, module, entity, type_arguments))
157 }
158}
159
160impl<'a> DamlVisitableElement<'a> for DamlType<'a> {
161 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
162 visitor.pre_visit_type(self);
163 match self {
164 DamlType::Var(var) => var.accept(visitor),
165 DamlType::List(args)
166 | DamlType::Optional(args)
167 | DamlType::TextMap(args)
168 | DamlType::GenMap(args)
169 | DamlType::Numeric(args) => args.iter().for_each(|arg| arg.accept(visitor)),
170 DamlType::ContractId(tycon) => tycon.as_ref().map_or_else(|| {}, |dr| dr.accept(visitor)),
171 DamlType::TyCon(tycon) | DamlType::BoxedTyCon(tycon) => tycon.accept(visitor),
172 DamlType::Forall(forall) => forall.accept(visitor),
173 DamlType::Struct(tuple) => tuple.accept(visitor),
174 DamlType::Syn(syn) => syn.accept(visitor),
175 DamlType::Int64
176 | DamlType::Text
177 | DamlType::Timestamp
178 | DamlType::Party
179 | DamlType::Bool
180 | DamlType::Unit
181 | DamlType::Date
182 | DamlType::Update
183 | DamlType::Scenario
184 | DamlType::Arrow
185 | DamlType::Any
186 | DamlType::TypeRep
187 | DamlType::Bignumeric
188 | DamlType::RoundingMode
189 | DamlType::AnyException
190 | DamlType::Nat(_) => {},
191 }
192 visitor.post_visit_type(self);
193 }
194}
195
196pub type DamlTypeSynName<'a> = DamlTyConName<'a>;
198
199#[derive(Debug, Serialize, Clone, ToStatic)]
201pub struct DamlSyn<'a> {
202 pub tysyn: Box<DamlTypeSynName<'a>>,
203 pub args: Vec<DamlType<'a>>,
204}
205
206impl<'a> DamlSyn<'a> {
207 pub fn new(tysyn: Box<DamlTypeSynName<'a>>, args: Vec<DamlType<'a>>) -> Self {
208 Self {
209 tysyn,
210 args,
211 }
212 }
213
214 pub fn tysyn(&self) -> &DamlTypeSynName<'a> {
215 &self.tysyn
216 }
217
218 pub fn args(&self) -> &[DamlType<'_>] {
219 &self.args
220 }
221}
222
223impl<'a> DamlVisitableElement<'a> for DamlSyn<'a> {
224 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
225 visitor.pre_visit_syn(self);
226 self.tysyn.accept(visitor);
227 self.args.iter().for_each(|field| field.accept(visitor));
228 visitor.post_visit_syn(self);
229 }
230}
231
232#[derive(Debug, Serialize, Clone, ToStatic)]
234pub struct DamlStruct<'a> {
235 pub fields: Vec<DamlField<'a>>,
236}
237
238impl<'a> DamlStruct<'a> {
239 pub fn new(fields: Vec<DamlField<'a>>) -> Self {
240 Self {
241 fields,
242 }
243 }
244
245 pub fn fields(&self) -> &[DamlField<'_>] {
246 &self.fields
247 }
248}
249
250impl<'a> DamlVisitableElement<'a> for DamlStruct<'a> {
251 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
252 visitor.pre_visit_struct(self);
253 self.fields.iter().for_each(|field| field.accept(visitor));
254 visitor.post_visit_struct(self);
255 }
256}
257
258#[derive(Debug, Serialize, Clone, ToStatic)]
260pub struct DamlForall<'a> {
261 pub vars: Vec<DamlTypeVarWithKind<'a>>,
262 pub body: Box<DamlType<'a>>,
263}
264
265impl<'a> DamlForall<'a> {
266 pub fn new(vars: Vec<DamlTypeVarWithKind<'a>>, body: Box<DamlType<'a>>) -> Self {
267 Self {
268 vars,
269 body,
270 }
271 }
272
273 pub fn vars(&self) -> &[DamlTypeVarWithKind<'_>] {
274 &self.vars
275 }
276
277 pub fn body(&self) -> &DamlType<'a> {
278 &self.body
279 }
280}
281
282impl<'a> DamlVisitableElement<'a> for DamlForall<'a> {
283 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
284 visitor.pre_visit_forall(self);
285 self.vars.iter().for_each(|var| var.accept(visitor));
286 self.body.accept(visitor);
287 visitor.post_visit_forall(self);
288 }
289}
290
291#[derive(Debug, Serialize, Clone, ToStatic)]
293pub struct DamlTyCon<'a> {
294 tycon: Box<DamlTyConName<'a>>,
295 type_arguments: Vec<DamlType<'a>>,
296}
297
298impl<'a> DamlTyCon<'a> {
299 pub fn new(tycon: Box<DamlTyConName<'a>>, type_arguments: Vec<DamlType<'a>>) -> Self {
300 Self {
301 tycon,
302 type_arguments,
303 }
304 }
305
306 pub fn new_absolute<'b, S: AsRef<str> + 'b>(
307 package_id: &'b str,
308 module: &'b [S],
309 entity: &'b str,
310 ) -> DamlTyCon<'b> {
311 Self::new_absolute_with_type_args(package_id, module, entity, vec![])
312 }
313
314 pub fn new_absolute_with_type_args<'b, S: AsRef<str> + 'b>(
315 package_id: &'b str,
316 module: &'b [S],
317 entity: &'b str,
318 type_arguments: Vec<DamlType<'b>>,
319 ) -> DamlTyCon<'b> {
320 DamlTyCon::new(Box::new(DamlTyConName::new_absolute(package_id, module, entity)), type_arguments)
321 }
322
323 pub fn type_arguments(&self) -> &[DamlType<'_>] {
324 &self.type_arguments
325 }
326
327 pub fn tycon(&self) -> &DamlTyConName<'_> {
328 &self.tycon
329 }
330}
331
332impl Hash for DamlTyCon<'_> {
333 fn hash<H: Hasher>(&self, state: &mut H) {
334 self.tycon.hash(state);
335 }
336}
337
338impl PartialEq for DamlTyCon<'_> {
340 fn eq(&self, other: &Self) -> bool {
341 self.tycon == other.tycon
342 }
343}
344
345impl Eq for DamlTyCon<'_> {}
346
347impl<'a> DamlVisitableElement<'a> for DamlTyCon<'a> {
348 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
349 visitor.pre_visit_tycon(self);
350 self.tycon.accept(visitor);
351 self.type_arguments.iter().for_each(|arg| arg.accept(visitor));
352 visitor.post_visit_tycon(self);
353 }
354}
355
356#[derive(Debug, Serialize, Clone, Hash, Eq, PartialEq, ToStatic)]
358pub enum DamlTyConName<'a> {
359 Local(DamlLocalTyCon<'a>),
360 NonLocal(DamlNonLocalTyCon<'a>),
361 Absolute(DamlAbsoluteTyCon<'a>),
362}
363
364impl<'a> DamlTyConName<'a> {
365 pub fn package_id(&self) -> &str {
366 match self {
367 DamlTyConName::Local(local) => &local.package_id,
368 DamlTyConName::NonLocal(non_local) => &non_local.target_package_id,
369 DamlTyConName::Absolute(abs) => &abs.package_id,
370 }
371 }
372
373 pub fn package_name(&self) -> &str {
374 match self {
375 DamlTyConName::Local(local) => &local.package_name,
376 DamlTyConName::NonLocal(non_local) => &non_local.target_package_name,
377 DamlTyConName::Absolute(abs) => &abs.package_name,
378 }
379 }
380
381 pub fn module_path(&self) -> impl Iterator<Item = &str> {
382 match self {
383 DamlTyConName::Local(local) => local.module_path.iter().map(AsRef::as_ref),
384 DamlTyConName::NonLocal(non_local) => non_local.target_module_path.iter().map(AsRef::as_ref),
385 DamlTyConName::Absolute(abs) => abs.module_path.iter().map(AsRef::as_ref),
386 }
387 }
388
389 pub fn data_name(&self) -> &str {
390 match self {
391 DamlTyConName::Local(local) => &local.data_name,
392 DamlTyConName::NonLocal(non_local) => &non_local.data_name,
393 DamlTyConName::Absolute(abs) => &abs.data_name,
394 }
395 }
396
397 pub fn new_absolute<'b, S: AsRef<str> + 'b>(
398 package_id: &'b str,
399 module: &'b [S],
400 entity: &'b str,
401 ) -> DamlTyConName<'b> {
402 DamlTyConName::Absolute(DamlAbsoluteTyCon::new(
403 entity.into(),
404 package_id.into(),
405 Cow::default(),
406 module.iter().map(AsRef::as_ref).map(Into::into).collect(),
407 ))
408 }
409
410 #[doc(hidden)]
412 pub(crate) fn reference_parts(&self) -> (&str, &[Cow<'_, str>], &str) {
413 match self {
414 DamlTyConName::Local(local) => (&local.package_id, &local.module_path, &local.data_name),
415 DamlTyConName::NonLocal(non_local) =>
416 (&non_local.target_package_id, &non_local.target_module_path, &non_local.data_name),
417 DamlTyConName::Absolute(abs) => (&abs.package_id, &abs.module_path, &abs.data_name),
418 }
419 }
420}
421
422impl Display for DamlTyConName<'_> {
423 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
424 match self {
425 DamlTyConName::Local(local) =>
426 write!(f, "{}:{}:{}", local.package_name, &local.module_path.join("."), local.data_name),
427 DamlTyConName::NonLocal(non_local) => write!(
428 f,
429 "{}:{}:{}",
430 non_local.target_package_name,
431 &non_local.target_module_path.join("."),
432 non_local.data_name
433 ),
434 DamlTyConName::Absolute(abs) =>
435 write!(f, "{}:{}:{}", abs.package_name, &abs.module_path.join("."), abs.data_name),
436 }
437 }
438}
439
440impl<'a> DamlVisitableElement<'a> for DamlTyConName<'a> {
441 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
442 visitor.pre_visit_tycon_name(self);
443 match self {
444 DamlTyConName::Local(local) => local.accept(visitor),
445 DamlTyConName::NonLocal(non_local) => non_local.accept(visitor),
446 DamlTyConName::Absolute(absolute) => absolute.accept(visitor),
447 }
448 visitor.post_visit_tycon_name(self);
449 }
450}
451
452impl PartialEq<DamlData<'_>> for DamlTyConName<'_> {
454 fn eq(&self, data: &DamlData<'_>) -> bool {
455 data == self
456 }
457}
458
459#[derive(Debug, Serialize, Clone, Hash, Eq, PartialEq, ToStatic)]
461pub struct DamlLocalTyCon<'a> {
462 data_name: Cow<'a, str>,
463 package_id: Cow<'a, str>,
464 package_name: Cow<'a, str>,
465 module_path: Vec<Cow<'a, str>>,
466}
467
468impl<'a> DamlLocalTyCon<'a> {
469 pub fn new(
470 data_name: Cow<'a, str>,
471 package_id: Cow<'a, str>,
472 package_name: Cow<'a, str>,
473 module_path: Vec<Cow<'a, str>>,
474 ) -> Self {
475 Self {
476 data_name,
477 package_id,
478 package_name,
479 module_path,
480 }
481 }
482
483 pub fn data_name(&self) -> &str {
484 &self.data_name
485 }
486
487 pub fn package_id(&self) -> &str {
488 &self.package_id
489 }
490
491 pub fn package_name(&self) -> &str {
492 &self.package_name
493 }
494
495 pub fn module_path(&self) -> impl Iterator<Item = &str> {
496 self.module_path.iter().map(AsRef::as_ref)
497 }
498}
499
500impl<'a> DamlVisitableElement<'a> for DamlLocalTyCon<'a> {
501 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
502 visitor.pre_visit_local_tycon(self);
503 visitor.post_visit_local_tycon(self);
504 }
505}
506
507#[derive(Debug, Serialize, Clone, Hash, Eq, PartialEq, ToStatic)]
509pub struct DamlNonLocalTyCon<'a> {
510 data_name: Cow<'a, str>,
511 source_package_id: Cow<'a, str>,
512 source_package_name: Cow<'a, str>,
513 source_module_path: Vec<Cow<'a, str>>,
514 target_package_id: Cow<'a, str>,
515 target_package_name: Cow<'a, str>,
516 target_module_path: Vec<Cow<'a, str>>,
517}
518
519impl<'a> DamlNonLocalTyCon<'a> {
520 pub fn new(
521 data_name: Cow<'a, str>,
522 source_package_id: Cow<'a, str>,
523 source_package_name: Cow<'a, str>,
524 source_module_path: Vec<Cow<'a, str>>,
525 target_package_id: Cow<'a, str>,
526 target_package_name: Cow<'a, str>,
527 target_module_path: Vec<Cow<'a, str>>,
528 ) -> Self {
529 Self {
530 data_name,
531 source_package_id,
532 source_package_name,
533 source_module_path,
534 target_package_id,
535 target_package_name,
536 target_module_path,
537 }
538 }
539
540 pub fn data_name(&self) -> &str {
541 &self.data_name
542 }
543
544 pub fn source_package_id(&self) -> &str {
545 &self.source_package_id
546 }
547
548 pub fn source_package_name(&self) -> &str {
549 &self.source_package_name
550 }
551
552 pub fn source_module_path(&self) -> impl Iterator<Item = &str> {
553 self.source_module_path.iter().map(AsRef::as_ref)
554 }
555
556 pub fn target_package_id(&self) -> &str {
557 &self.target_package_id
558 }
559
560 pub fn target_package_name(&self) -> &str {
561 &self.target_package_name
562 }
563
564 pub fn target_module_path(&self) -> impl Iterator<Item = &str> {
565 self.target_module_path.iter().map(AsRef::as_ref)
566 }
567}
568
569impl<'a> DamlVisitableElement<'a> for DamlNonLocalTyCon<'a> {
570 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
571 visitor.pre_visit_non_local_tycon(self);
572 visitor.post_visit_non_local_tycon(self);
573 }
574}
575
576#[derive(Debug, Serialize, Clone, Hash, Eq, PartialEq, ToStatic)]
578pub struct DamlAbsoluteTyCon<'a> {
579 data_name: Cow<'a, str>,
580 package_id: Cow<'a, str>,
581 package_name: Cow<'a, str>,
582 module_path: Vec<Cow<'a, str>>,
583}
584
585impl<'a> DamlAbsoluteTyCon<'a> {
586 pub fn new(
587 data_name: Cow<'a, str>,
588 package_id: Cow<'a, str>,
589 package_name: Cow<'a, str>,
590 module_path: Vec<Cow<'a, str>>,
591 ) -> Self {
592 Self {
593 data_name,
594 package_id,
595 package_name,
596 module_path,
597 }
598 }
599
600 pub fn data_name(&self) -> &str {
601 &self.data_name
602 }
603
604 pub fn package_id(&self) -> &str {
605 &self.package_id
606 }
607
608 pub fn package_name(&self) -> &str {
609 &self.package_name
610 }
611
612 pub fn module_path(&self) -> impl Iterator<Item = &str> {
613 self.module_path.iter().map(AsRef::as_ref)
614 }
615}
616
617impl<'a> DamlVisitableElement<'a> for DamlAbsoluteTyCon<'a> {
618 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
619 visitor.pre_visit_absolute_tycon(self);
620 visitor.post_visit_absolute_tycon(self);
621 }
622}
623
624#[derive(Debug, Serialize, Clone, ToStatic)]
626pub struct DamlVar<'a> {
627 var: Cow<'a, str>,
628 type_arguments: Vec<DamlType<'a>>,
629}
630
631impl<'a> DamlVar<'a> {
632 pub fn new(var: Cow<'a, str>, type_arguments: Vec<DamlType<'a>>) -> Self {
633 Self {
634 var,
635 type_arguments,
636 }
637 }
638
639 pub fn var(&self) -> &str {
640 &self.var
641 }
642
643 pub fn type_arguments(&self) -> &[DamlType<'a>] {
644 &self.type_arguments
645 }
646}
647
648impl<'a> DamlVisitableElement<'a> for DamlVar<'a> {
649 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
650 visitor.pre_visit_var(self);
651 self.type_arguments.iter().for_each(|arg| arg.accept(visitor));
652 visitor.post_visit_var(self);
653 }
654}