daml_lf/element/
daml_archive.rs

1use crate::element::daml_package::DamlPackage;
2use crate::element::visitor::{DamlElementVisitor, DamlVisitableElement};
3use crate::element::{serialize, DamlData, DamlTyCon, DamlTyConName};
4#[cfg(feature = "full")]
5use crate::element::{DamlDefValue, DamlValueName};
6use bounded_static::ToStatic;
7use itertools::Itertools;
8use serde::Serialize;
9use std::borrow::Cow;
10use std::collections::HashMap;
11
12/// A Daml Archive.
13#[derive(Debug, Serialize, Clone, Default, ToStatic)]
14pub struct DamlArchive<'a> {
15    name: Cow<'a, str>,
16    main_package_id: Cow<'a, str>,
17    #[serde(serialize_with = "serialize::serialize_map")]
18    packages: HashMap<Cow<'a, str>, DamlPackage<'a>>,
19}
20
21impl<'a> DamlArchive<'a> {
22    ///
23    pub const fn new(
24        name: Cow<'a, str>,
25        main_package_id: Cow<'a, str>,
26        packages: HashMap<Cow<'a, str>, DamlPackage<'a>>,
27    ) -> Self {
28        Self {
29            name,
30            main_package_id,
31            packages,
32        }
33    }
34
35    pub fn name(&self) -> &str {
36        &self.name
37    }
38
39    /// Return the package id of the main `DamlPackage` contained in this `DamlArchive`.
40    pub fn main_package_id(&self) -> &str {
41        &self.main_package_id
42    }
43
44    /// Return an Iterator of the [`DamlPackage`] in this [`DamlArchive`].
45    pub fn packages(&self) -> impl Iterator<Item = &DamlPackage<'_>> {
46        self.packages.values()
47    }
48
49    /// Return the first [`DamlPackage`] in this [`DamlArchive`] which has the given `name` or `None` if no such
50    /// package exists.
51    pub fn package_by_name(&self, name: &str) -> Option<&DamlPackage<'_>> {
52        self.packages.values().find(|p| p.name() == name)
53    }
54
55    /// Return the main [`DamlPackage`] in this [`DamlArchive`] or `None` if no such package exists.
56    pub fn main_package(&self) -> Option<&DamlPackage<'_>> {
57        self.packages.get(&self.main_package_id)
58    }
59
60    /// Retrieve a `DamlData` contained within this `DamlArchive` referred to by the supplied `DamlTyCon` or `None` if
61    /// not such data item exists.
62    ///
63    /// DOCME
64    pub fn data_by_tycon<'b>(&'a self, tycon: &'b DamlTyCon<'_>) -> Option<&'a DamlData<'a>> {
65        self.data_by_tycon_name(tycon.tycon())
66    }
67
68    /// Retrieve a `DamlData` contained within this `DamlArchive` referred to by the supplied `DamlTyConName` or `None`
69    /// if not such data item exists.
70    ///
71    /// DOCME
72    pub fn data_by_tycon_name<'b>(&'a self, tycon_name: &'b DamlTyConName<'_>) -> Option<&'a DamlData<'a>> {
73        let (package_id, module_path, data_name) = tycon_name.reference_parts();
74        self.data(package_id, module_path, data_name)
75    }
76
77    /// Retrieve a `DamlData` contained within this `DamlArchive` referred to by the supplied package id, module path &
78    /// name or `None` if not such data item exists.
79    ///
80    /// DOCME
81    pub fn data<P, M, D>(&'a self, package_id: P, module_path: &[M], data_name: D) -> Option<&'a DamlData<'a>>
82    where
83        P: AsRef<str>,
84        M: AsRef<str>,
85        D: AsRef<str>,
86    {
87        self.packages
88            .get(package_id.as_ref())?
89            .root_module()
90            .child_module_path(module_path)?
91            .data_type(data_name.as_ref())
92    }
93
94    /// Retrieve a `DamlDefValue` for a given `DamlValueName` or `None` if no such value exists in this `DamlArchive`.
95    ///
96    /// DOCME
97    #[cfg(feature = "full")]
98    pub fn value_by_name<'b>(&'a self, name: &'b DamlValueName<'_>) -> Option<&'a DamlDefValue<'a>> {
99        let (package_id, module_path, name) = name.reference_parts();
100        self.value(package_id, module_path, name)
101    }
102
103    /// Retrieve a `DamlDefValue` for the supplied package id, module path & name or `None` if no such value exists in
104    /// this `DamlArchive`.
105    ///
106    /// DOCME
107    #[cfg(feature = "full")]
108    pub fn value<P, M, D>(&'a self, package_id: P, module_path: &[M], name: D) -> Option<&'a DamlDefValue<'a>>
109    where
110        P: AsRef<str>,
111        M: AsRef<str>,
112        D: AsRef<str>,
113    {
114        self.packages.get(package_id.as_ref())?.root_module().child_module_path(module_path)?.value(name.as_ref())
115    }
116}
117
118impl<'a> DamlVisitableElement<'a> for DamlArchive<'a> {
119    fn accept(&'a self, visitor: &'a mut impl DamlElementVisitor) {
120        visitor.pre_visit_archive(self);
121        if visitor.sort_elements() {
122            self.packages.values().sorted_by_key(|p| p.name()).for_each(|package| package.accept(visitor));
123        } else {
124            self.packages.values().for_each(|package| package.accept(visitor));
125        }
126        visitor.post_visit_archive(self);
127    }
128}