daml_lf/element/
daml_module.rs1use crate::element::daml_data::DamlData;
2use crate::element::visitor::DamlElementVisitor;
3#[cfg(feature = "full")]
4use crate::element::DamlDefValue;
5use crate::element::DamlVisitableElement;
6use crate::element::{serialize, DamlType, DamlTypeVarWithKind};
7use bounded_static::ToStatic;
8use itertools::Itertools;
9use serde::Serialize;
10use std::borrow::Cow;
11use std::collections::HashMap;
12use std::iter::once;
13
14const ROOT_MODULE_NAME: &str = "root";
15
16#[derive(Debug, Serialize, Clone, ToStatic)]
18pub struct DamlModule<'a> {
19 path: Vec<Cow<'a, str>>,
20 flags: DamlFeatureFlags,
21 synonyms: Vec<DamlDefTypeSyn<'a>>,
22 #[serde(serialize_with = "serialize::serialize_map")]
23 child_modules: HashMap<Cow<'a, str>, DamlModule<'a>>,
24 #[serde(serialize_with = "serialize::serialize_map")]
25 data_types: HashMap<Cow<'a, str>, DamlData<'a>>,
26 #[cfg(feature = "full")]
27 values: HashMap<Cow<'a, str>, DamlDefValue<'a>>,
28}
29
30impl<'a> DamlModule<'a> {
31 pub fn new_root() -> Self {
33 Self::new_empty(vec![])
34 }
35
36 pub fn new_leaf(
38 path: Vec<Cow<'a, str>>,
39 flags: DamlFeatureFlags,
40 synonyms: Vec<DamlDefTypeSyn<'a>>,
41 data_types: HashMap<Cow<'a, str>, DamlData<'a>>,
42 #[cfg(feature = "full")] values: HashMap<Cow<'a, str>, DamlDefValue<'a>>,
43 ) -> Self {
44 Self {
45 path,
46 flags,
47 synonyms,
48 child_modules: HashMap::default(),
49 data_types,
50 #[cfg(feature = "full")]
51 values,
52 }
53 }
54
55 pub fn flags(&self) -> &DamlFeatureFlags {
57 &self.flags
58 }
59
60 pub fn synonyms(&self) -> &[DamlDefTypeSyn<'_>] {
62 &self.synonyms
63 }
64
65 pub fn path(&self) -> impl Iterator<Item = &str> {
67 self.path.iter().map(AsRef::as_ref)
68 }
69
70 pub fn child_modules(&self) -> impl Iterator<Item = &DamlModule<'a>> {
72 self.child_modules.values()
73 }
74
75 pub fn data_types(&self) -> impl Iterator<Item = &DamlData<'a>> {
77 self.data_types.values()
78 }
79
80 #[cfg(feature = "full")]
82 pub fn values(&self) -> impl Iterator<Item = &DamlDefValue<'a>> {
83 self.values.values()
84 }
85
86 pub fn is_root(&self) -> bool {
88 self.path.is_empty()
89 }
90
91 pub fn is_leaf(&self) -> bool {
93 self.child_modules.is_empty()
94 }
95
96 pub fn local_name(&self) -> &str {
98 self.path.last().map(AsRef::as_ref).map_or_else(|| ROOT_MODULE_NAME, AsRef::as_ref)
99 }
100
101 pub fn child_module<S: AsRef<str>>(&self, name: S) -> Option<&DamlModule<'_>> {
103 self.child_modules.get(name.as_ref())
104 }
105
106 pub fn child_module_path<'b, S: AsRef<str>>(&'a self, relative_path: &'b [S]) -> Option<&'a DamlModule<'a>> {
108 match relative_path {
109 [] => Some(self),
110 [head, tail @ ..] => match self.child_module(head.as_ref()) {
111 Some(m) => m.child_module_path(tail),
112 None => None,
113 },
114 }
115 }
116
117 pub fn data_type<S: AsRef<str>>(&self, name: S) -> Option<&DamlData<'a>> {
119 self.data_types.get(name.as_ref())
120 }
121
122 #[cfg(feature = "full")]
124 pub fn value<S: AsRef<str>>(&self, name: S) -> Option<&DamlDefValue<'a>> {
125 self.values.get(name.as_ref())
126 }
127
128 #[doc(hidden)]
130 pub(crate) fn child_module_or_new(&mut self, name: &'a str) -> &mut Self {
131 let path = &self.path;
132 self.child_modules.entry(Cow::from(name)).or_insert_with(|| {
133 DamlModule::new_empty(path.iter().map(ToOwned::to_owned).chain(once(Cow::from(name))).collect())
134 })
135 }
136
137 #[doc(hidden)]
142 pub(crate) fn take_from(&mut self, other: Self) {
143 debug_assert_eq!(self.path, other.path);
144 self.flags = other.flags;
145 self.data_types = other.data_types;
146 self.synonyms = other.synonyms;
147 #[cfg(feature = "full")]
148 {
149 self.values = other.values;
150 }
151 }
152
153 fn new_empty(path: Vec<Cow<'a, str>>) -> Self {
155 Self {
156 path,
157 flags: DamlFeatureFlags::default(),
158 synonyms: Vec::default(),
159 child_modules: HashMap::default(),
160 data_types: HashMap::default(),
161 #[cfg(feature = "full")]
162 values: HashMap::default(),
163 }
164 }
165}
166
167impl<'a> DamlVisitableElement<'a> for DamlModule<'a> {
168 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
169 visitor.pre_visit_module(self);
170 self.synonyms.iter().for_each(|syn| syn.accept(visitor));
171 if visitor.sort_elements() {
172 self.data_types.values().sorted_by_key(|ty| ty.name()).for_each(|data| data.accept(visitor));
173 self.child_modules.values().sorted_by_key(|&m| m.path.clone()).for_each(|module| module.accept(visitor));
174 } else {
175 self.data_types.values().for_each(|data| data.accept(visitor));
176 self.child_modules.values().for_each(|module| module.accept(visitor));
177 }
178 #[cfg(feature = "full")]
179 self.values.values().for_each(|value| value.accept(visitor));
180 visitor.post_visit_module(self);
181 }
182}
183
184#[derive(Debug, Serialize, Clone, ToStatic)]
186pub struct DamlDefTypeSyn<'a> {
187 params: Vec<DamlTypeVarWithKind<'a>>,
188 ty: DamlType<'a>,
189 name: Vec<Cow<'a, str>>,
190}
191
192impl<'a> DamlDefTypeSyn<'a> {
193 pub fn new(params: Vec<DamlTypeVarWithKind<'a>>, ty: DamlType<'a>, name: Vec<Cow<'a, str>>) -> Self {
195 Self {
196 params,
197 ty,
198 name,
199 }
200 }
201
202 pub fn params(&self) -> &[DamlTypeVarWithKind<'_>] {
204 &self.params
205 }
206
207 pub fn ty(&self) -> &DamlType<'_> {
209 &self.ty
210 }
211
212 pub fn name(&self) -> impl Iterator<Item = &str> {
214 self.name.iter().map(AsRef::as_ref)
215 }
216}
217
218impl<'a> DamlVisitableElement<'a> for DamlDefTypeSyn<'a> {
219 fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
220 visitor.pre_visit_def_type_syn(self);
221 self.params.iter().for_each(|param| param.accept(visitor));
222 self.ty.accept(visitor);
223 visitor.post_visit_def_type_syn(self);
224 }
225}
226
227#[derive(Debug, Serialize, Copy, Clone, Default, ToStatic)]
229pub struct DamlFeatureFlags {
230 forbid_party_literals: bool,
231 dont_divulge_contract_ids_in_create_arguments: bool,
232 dont_disclose_non_consuming_choices_to_observers: bool,
233}
234
235impl DamlFeatureFlags {
236 pub fn new(
237 forbid_party_literals: bool,
238 dont_divulge_contract_ids_in_create_arguments: bool,
239 dont_disclose_non_consuming_choices_to_observers: bool,
240 ) -> Self {
241 Self {
242 forbid_party_literals,
243 dont_divulge_contract_ids_in_create_arguments,
244 dont_disclose_non_consuming_choices_to_observers,
245 }
246 }
247
248 pub fn forbid_party_literals(self) -> bool {
250 self.forbid_party_literals
251 }
252
253 pub fn dont_divulge_contract_ids_in_create_arguments(self) -> bool {
255 self.dont_divulge_contract_ids_in_create_arguments
256 }
257
258 pub fn dont_disclose_non_consuming_choices_to_observers(self) -> bool {
260 self.dont_disclose_non_consuming_choices_to_observers
261 }
262}