1use std::borrow::Cow;
2use std::convert::{TryFrom, TryInto};
3
4use crate::convert::field_payload::DamlFieldPayload;
5use crate::convert::interned::{InternableDottedName, InternableString, PackageInternedResolver};
6use crate::convert::typevar_payload::DamlTypeVarWithKindPayload;
7use crate::convert::util::Required;
8use crate::convert::wrapper::PayloadElementWrapper;
9use crate::error::{DamlLfConvertError, DamlLfConvertResult};
10use crate::lf_protobuf::com::daml::daml_lf_1::r#type::{Con, Forall, Struct, Sum, Syn, Var};
11use crate::lf_protobuf::com::daml::daml_lf_1::{package_ref, PrimType, TypeSynName};
12use crate::lf_protobuf::com::daml::daml_lf_1::{ModuleRef, PackageRef, Type, TypeConName};
13
14pub type DamlTypeWrapper<'a> = PayloadElementWrapper<'a, &'a DamlTypePayload<'a>>;
16
17#[derive(Debug)]
18pub enum DamlTypePayload<'a> {
19 ContractId(Option<Box<DamlTypePayload<'a>>>),
20 Int64,
21 Numeric(Vec<DamlTypePayload<'a>>),
22 Text,
23 Timestamp,
24 Party,
25 Bool,
26 Unit,
27 Date,
28 List(Vec<DamlTypePayload<'a>>),
29 Update,
30 Scenario,
31 TextMap(Vec<DamlTypePayload<'a>>),
32 GenMap(Vec<DamlTypePayload<'a>>),
33 Optional(Vec<DamlTypePayload<'a>>),
34 TyCon(DamlTyConPayload<'a>),
35 Var(DamlVarPayload<'a>),
36 Arrow,
37 Any,
38 TypeRep,
39 Bignumeric,
40 RoundingMode,
41 AnyException,
42 Nat(u8),
43 Forall(DamlForallPayload<'a>),
44 Struct(DamlStructPayload<'a>),
45 Syn(DamlSynPayload<'a>),
46 Interned(i32),
47}
48
49impl<'a> DamlTypePayload<'a> {
50 pub fn name_for_error(&self) -> &'static str {
51 match self {
52 DamlTypePayload::ContractId(_) => "ContractId",
53 DamlTypePayload::Int64 => "Int64",
54 DamlTypePayload::Numeric(_) => "Numeric",
55 DamlTypePayload::Text => "Text",
56 DamlTypePayload::Timestamp => "Timestamp",
57 DamlTypePayload::Party => "Party",
58 DamlTypePayload::Bool => "Bool",
59 DamlTypePayload::Unit => "Unit",
60 DamlTypePayload::Date => "Date",
61 DamlTypePayload::List(_) => "List",
62 DamlTypePayload::Update => "Update",
63 DamlTypePayload::Scenario => "Scenario",
64 DamlTypePayload::TextMap(_) => "TextMap",
65 DamlTypePayload::GenMap(_) => "GenMap",
66 DamlTypePayload::Optional(_) => "Optional",
67 DamlTypePayload::TyCon(_) => "TyCon",
68 DamlTypePayload::Var(_) => "Var",
69 DamlTypePayload::Arrow => "Arrow",
70 DamlTypePayload::Any => "Any",
71 DamlTypePayload::TypeRep => "TypeRep",
72 DamlTypePayload::Bignumeric => "Bignumeric",
73 DamlTypePayload::RoundingMode => "RoundingMode",
74 DamlTypePayload::AnyException => "AnyException",
75 DamlTypePayload::Nat(_) => "Nat",
76 DamlTypePayload::Forall(_) => "Forall",
77 DamlTypePayload::Struct(_) => "Struct",
78 DamlTypePayload::Syn(_) => "Syn",
79 DamlTypePayload::Interned(_) => "Interned",
80 }
81 }
82}
83
84pub const LEGACY_DECIMAL_NAT: u8 = 10;
86
87impl<'a> TryFrom<&'a Type> for DamlTypePayload<'a> {
88 type Error = DamlLfConvertError;
89
90 fn try_from(ty: &'a Type) -> DamlLfConvertResult<Self> {
91 match ty.sum.as_ref().req()? {
92 Sum::Prim(prim) => match PrimType::from_i32(prim.prim).req()? {
93 PrimType::Unit => Ok(DamlTypePayload::Unit),
94 PrimType::Bool => Ok(DamlTypePayload::Bool),
95 PrimType::Int64 => Ok(DamlTypePayload::Int64),
96 PrimType::Numeric => Ok(DamlTypePayload::Numeric(try_from_type_args(&prim.args)?)),
97 PrimType::Decimal => Ok(DamlTypePayload::Numeric(vec![DamlTypePayload::Nat(LEGACY_DECIMAL_NAT)])),
98 PrimType::Text => Ok(DamlTypePayload::Text),
99 PrimType::Timestamp => Ok(DamlTypePayload::Timestamp),
100 PrimType::Party => Ok(DamlTypePayload::Party),
101 PrimType::List => Ok(DamlTypePayload::List(try_from_type_args(&prim.args)?)),
102 PrimType::Update => Ok(DamlTypePayload::Update),
103 PrimType::Scenario => Ok(DamlTypePayload::Scenario),
104 PrimType::Date => Ok(DamlTypePayload::Date),
105 PrimType::ContractId => match prim.args.as_slice() {
106 [ty] => Ok(DamlTypePayload::ContractId(Some(Box::new(DamlTypePayload::try_from(ty)?)))),
107 args if !args.is_empty() => Err(DamlLfConvertError::UnexpectedContractIdTypeArguments),
108 _ => Ok(DamlTypePayload::ContractId(None)),
109 },
110 PrimType::Optional => Ok(DamlTypePayload::Optional(try_from_type_args(&prim.args)?)),
111 PrimType::Arrow => Ok(DamlTypePayload::Arrow),
112 PrimType::Textmap => Ok(DamlTypePayload::TextMap(try_from_type_args(&prim.args)?)),
113 PrimType::Genmap => Ok(DamlTypePayload::GenMap(try_from_type_args(&prim.args)?)),
114 PrimType::Any => Ok(DamlTypePayload::Any),
115 PrimType::TypeRep => Ok(DamlTypePayload::TypeRep),
116 PrimType::Bignumeric => Ok(DamlTypePayload::Bignumeric),
117 PrimType::RoundingMode => Ok(DamlTypePayload::RoundingMode),
118 PrimType::AnyException => Ok(DamlTypePayload::AnyException),
119 },
120 Sum::Con(con) => Ok(DamlTypePayload::TyCon(DamlTyConPayload::try_from(con)?)),
121 Sum::Var(var) => Ok(DamlTypePayload::Var(DamlVarPayload::try_from(var)?)),
122 Sum::Nat(n) =>
123 if *n >= 0 && *n <= 37 {
124 #[allow(clippy::cast_possible_truncation)]
125 Ok(DamlTypePayload::Nat(*n as u8))
126 } else {
127 Err(DamlLfConvertError::NatOutOfRange(*n))
128 },
129 Sum::Forall(forall) => Ok(DamlTypePayload::Forall(DamlForallPayload::try_from(forall.as_ref())?)),
130 Sum::Struct(tuple) => Ok(DamlTypePayload::Struct(DamlStructPayload::try_from(tuple)?)),
131 Sum::Syn(syn) => Ok(DamlTypePayload::Syn(DamlSynPayload::try_from(syn)?)),
132 Sum::Interned(i) => Ok(DamlTypePayload::Interned(*i)),
133 }
134 }
135}
136
137pub type DamlSynWrapper<'a> = PayloadElementWrapper<'a, &'a DamlSynPayload<'a>>;
138
139#[derive(Debug)]
140pub struct DamlSynPayload<'a> {
141 pub tysyn: DamlTypeSynNamePayload<'a>,
142 pub args: Vec<DamlTypePayload<'a>>,
143}
144
145impl<'a> DamlSynPayload<'a> {
146 pub fn new(tysyn: DamlTypeSynNamePayload<'a>, args: Vec<DamlTypePayload<'a>>) -> Self {
147 Self {
148 tysyn,
149 args,
150 }
151 }
152}
153
154impl<'a> TryFrom<&'a Syn> for DamlSynPayload<'a> {
155 type Error = DamlLfConvertError;
156
157 fn try_from(syn: &'a Syn) -> DamlLfConvertResult<Self> {
158 let tysyn = DamlTypeSynNamePayload::try_from(syn.tysyn.as_ref().req()?)?;
159 let args = try_from_type_args(&syn.args)?;
160 Ok(DamlSynPayload::new(tysyn, args))
161 }
162}
163
164pub type DamlTypeSynNameWrapper<'a> = PayloadElementWrapper<'a, &'a DamlTypeSynNamePayload<'a>>;
165
166#[derive(Debug)]
167pub struct DamlTypeSynNamePayload<'a> {
168 pub package_ref: DamlPackageRefPayload<'a>,
169 pub module_path: InternableDottedName<'a>,
170 pub data_name: InternableDottedName<'a>,
171}
172
173impl<'a> DamlTypeSynNamePayload<'a> {
174 pub fn new(
175 package_ref: DamlPackageRefPayload<'a>,
176 module_path: InternableDottedName<'a>,
177 data_name: InternableDottedName<'a>,
178 ) -> Self {
179 Self {
180 package_ref,
181 module_path,
182 data_name,
183 }
184 }
185}
186
187impl<'a> TryFrom<&'a TypeSynName> for DamlTypeSynNamePayload<'a> {
188 type Error = DamlLfConvertError;
189
190 fn try_from(tysyn: &'a TypeSynName) -> DamlLfConvertResult<Self> {
191 match tysyn {
192 TypeSynName {
193 module:
194 Some(ModuleRef {
195 package_ref: Some(package_ref),
196 module_name: Some(module_name),
197 }),
198 name: Some(data_name),
199 } => Ok(Self::new(
200 package_ref.try_into()?,
201 InternableDottedName::from(module_name),
202 InternableDottedName::from(data_name),
203 )),
204 _ => Err(DamlLfConvertError::MissingRequiredField),
205 }
206 }
207}
208
209pub type DamlStructWrapper<'a> = PayloadElementWrapper<'a, &'a DamlStructPayload<'a>>;
211
212#[derive(Debug)]
213pub struct DamlStructPayload<'a> {
214 pub fields: Vec<DamlFieldPayload<'a>>,
215}
216
217impl<'a> DamlStructPayload<'a> {
218 pub fn new(fields: Vec<DamlFieldPayload<'a>>) -> Self {
219 Self {
220 fields,
221 }
222 }
223}
224
225impl<'a> TryFrom<&'a Struct> for DamlStructPayload<'a> {
226 type Error = DamlLfConvertError;
227
228 fn try_from(tuple: &'a Struct) -> DamlLfConvertResult<Self> {
229 let fields = tuple.fields.iter().map(DamlFieldPayload::try_from).collect::<DamlLfConvertResult<Vec<_>>>()?;
230 Ok(DamlStructPayload::new(fields))
231 }
232}
233
234pub type DamlForallWrapper<'a> = PayloadElementWrapper<'a, &'a DamlForallPayload<'a>>;
236
237#[derive(Debug)]
238pub struct DamlForallPayload<'a> {
239 pub vars: Vec<DamlTypeVarWithKindPayload<'a>>,
240 pub body: Box<DamlTypePayload<'a>>,
241}
242
243impl<'a> DamlForallPayload<'a> {
244 pub fn new(vars: Vec<DamlTypeVarWithKindPayload<'a>>, body: Box<DamlTypePayload<'a>>) -> Self {
245 Self {
246 vars,
247 body,
248 }
249 }
250}
251
252impl<'a> TryFrom<&'a Forall> for DamlForallPayload<'a> {
253 type Error = DamlLfConvertError;
254
255 fn try_from(forall: &'a Forall) -> DamlLfConvertResult<Self> {
256 let vars =
257 forall.vars.iter().map(DamlTypeVarWithKindPayload::try_from).collect::<DamlLfConvertResult<Vec<_>>>()?;
258 let body = DamlTypePayload::try_from(forall.body.as_ref().req()?.as_ref())?;
259 Ok(DamlForallPayload::new(vars, Box::new(body)))
260 }
261}
262
263pub type DamlTyConWrapper<'a> = PayloadElementWrapper<'a, &'a DamlTyConPayload<'a>>;
265
266#[derive(Debug)]
267pub struct DamlTyConPayload<'a> {
268 pub package_ref: DamlPackageRefPayload<'a>,
269 pub module_path: InternableDottedName<'a>,
270 pub data_name: InternableDottedName<'a>,
271 pub type_arguments: Vec<DamlTypePayload<'a>>,
272}
273
274impl<'a> DamlTyConPayload<'a> {
275 pub fn new(
276 package_ref: DamlPackageRefPayload<'a>,
277 module_path: InternableDottedName<'a>,
278 data_name: InternableDottedName<'a>,
279 type_arguments: Vec<DamlTypePayload<'a>>,
280 ) -> Self {
281 Self {
282 package_ref,
283 module_path,
284 data_name,
285 type_arguments,
286 }
287 }
288}
289
290impl<'a> TryFrom<&'a Con> for DamlTyConPayload<'a> {
291 type Error = DamlLfConvertError;
292
293 fn try_from(con: &'a Con) -> DamlLfConvertResult<Self> {
294 match con {
295 Con {
296 tycon:
297 Some(TypeConName {
298 module:
299 Some(ModuleRef {
300 package_ref: Some(package_ref),
301 module_name: Some(module_name),
302 }),
303 name: Some(data_name),
304 }),
305 args,
306 } => Ok(Self::new(
307 package_ref.try_into()?,
308 InternableDottedName::from(module_name),
309 InternableDottedName::from(data_name),
310 try_from_type_args(args)?,
311 )),
312 _ => Err(DamlLfConvertError::MissingRequiredField),
313 }
314 }
315}
316
317pub type DamlTyConNameWrapper<'a> = PayloadElementWrapper<'a, &'a DamlTyConNamePayload<'a>>;
318
319#[derive(Debug)]
320pub struct DamlTyConNamePayload<'a> {
321 pub package_ref: DamlPackageRefPayload<'a>,
322 pub module_path: InternableDottedName<'a>,
323 pub data_name: InternableDottedName<'a>,
324}
325
326impl<'a> DamlTyConNamePayload<'a> {
327 pub fn new(
328 package_ref: DamlPackageRefPayload<'a>,
329 module_path: InternableDottedName<'a>,
330 data_name: InternableDottedName<'a>,
331 ) -> Self {
332 Self {
333 package_ref,
334 module_path,
335 data_name,
336 }
337 }
338}
339
340impl<'a> TryFrom<&'a TypeConName> for DamlTyConNamePayload<'a> {
341 type Error = DamlLfConvertError;
342
343 fn try_from(con: &'a TypeConName) -> DamlLfConvertResult<Self> {
344 match con {
345 TypeConName {
346 module:
347 Some(ModuleRef {
348 package_ref: Some(package_ref),
349 module_name: Some(module_name),
350 }),
351 name: Some(data_name),
352 } => Ok(Self::new(
353 package_ref.try_into()?,
354 InternableDottedName::from(module_name),
355 InternableDottedName::from(data_name),
356 )),
357 _ => Err(DamlLfConvertError::MissingRequiredField),
358 }
359 }
360}
361
362#[derive(Debug, PartialEq)]
363pub enum DamlPackageRefPayload<'a> {
364 This,
365 PackageId(&'a str),
366 InternedId(i32),
367}
368
369impl<'a> DamlPackageRefPayload<'a> {
370 pub fn resolve(&self, resolver: &'a impl PackageInternedResolver) -> DamlLfConvertResult<Cow<'a, str>> {
371 Ok(match self {
372 DamlPackageRefPayload::This => Cow::from(resolver.package_id()),
373 &DamlPackageRefPayload::PackageId(s) => Cow::from(s),
374 &DamlPackageRefPayload::InternedId(i) => resolver.resolve_string(i)?,
375 })
376 }
377}
378
379impl<'a> TryFrom<&'a PackageRef> for DamlPackageRefPayload<'a> {
380 type Error = DamlLfConvertError;
381
382 fn try_from(package_ref: &'a PackageRef) -> DamlLfConvertResult<Self> {
383 Ok(match package_ref.sum.as_ref().req()? {
384 package_ref::Sum::Self_(_) => DamlPackageRefPayload::This,
385 package_ref::Sum::PackageIdStr(s) => DamlPackageRefPayload::PackageId(s.as_str()),
386 &package_ref::Sum::PackageIdInternedStr(i) => DamlPackageRefPayload::InternedId(i),
387 })
388 }
389}
390
391pub type DamlVarWrapper<'a> = PayloadElementWrapper<'a, &'a DamlVarPayload<'a>>;
393
394#[derive(Debug)]
395pub struct DamlVarPayload<'a> {
396 pub var: InternableString<'a>,
397 pub type_arguments: Vec<DamlTypePayload<'a>>,
398}
399
400impl<'a> DamlVarPayload<'a> {
401 pub fn new(var: InternableString<'a>, type_arguments: Vec<DamlTypePayload<'a>>) -> Self {
402 Self {
403 var,
404 type_arguments,
405 }
406 }
407}
408
409impl<'a> TryFrom<&'a Var> for DamlVarPayload<'a> {
410 type Error = DamlLfConvertError;
411
412 fn try_from(var: &'a Var) -> DamlLfConvertResult<Self> {
413 Ok(DamlVarPayload::new(InternableString::from(var.var.as_ref().req()?), try_from_type_args(&var.args)?))
414 }
415}
416
417fn try_from_type_args(args: &[Type]) -> DamlLfConvertResult<Vec<DamlTypePayload<'_>>> {
418 args.iter().map(DamlTypePayload::try_from).collect::<DamlLfConvertResult<Vec<_>>>()
419}