miden_mast_package/package/
manifest.rs

1use alloc::{collections::BTreeMap, vec::Vec};
2use core::fmt;
3
4use miden_assembly_syntax::ast::{AttributeSet, QualifiedProcedureName, types::FunctionType};
5use miden_core::{Word, utils::DisplayHex};
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::Dependency;
10
11// PACKAGE MANIFEST
12// ================================================================================================
13
14/// The manifest of a package, containing the set of package dependencies (libraries or packages)
15/// and exported procedures and their signatures, if known.
16#[derive(Debug, Default, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
18pub struct PackageManifest {
19    /// The set of exports in this package.
20    pub(super) exports: BTreeMap<QualifiedProcedureName, PackageExport>,
21    /// The libraries (packages) linked against by this package, which must be provided when
22    /// executing the program.
23    pub(super) dependencies: Vec<Dependency>,
24}
25
26impl PackageManifest {
27    pub fn new(exports: impl IntoIterator<Item = PackageExport>) -> Self {
28        let exports = exports.into_iter().map(|export| (export.name.clone(), export)).collect();
29        Self {
30            exports,
31            dependencies: Default::default(),
32        }
33    }
34
35    /// Extend this manifest with the provided dependencies
36    pub fn with_dependencies(mut self, dependencies: impl IntoIterator<Item = Dependency>) -> Self {
37        self.dependencies.extend(dependencies);
38        self
39    }
40
41    /// Add a dependency to the manifest
42    pub fn add_dependency(&mut self, dependency: Dependency) {
43        self.dependencies.push(dependency);
44    }
45
46    /// Get the number of dependencies of this package
47    pub fn num_dependencies(&self) -> usize {
48        self.dependencies.len()
49    }
50
51    /// Get an iterator over the dependencies of this package
52    pub fn dependencies(&self) -> impl Iterator<Item = &Dependency> {
53        self.dependencies.iter()
54    }
55
56    /// Get the number of procedures exported from this package
57    pub fn num_exports(&self) -> usize {
58        self.exports.len()
59    }
60
61    /// Get an iterator over the exports in this package
62    pub fn exports(&self) -> impl Iterator<Item = &PackageExport> {
63        self.exports.values()
64    }
65
66    /// Get information about an export by it's qualified name
67    pub fn get_export(&self, name: &QualifiedProcedureName) -> Option<&PackageExport> {
68        self.exports.get(name)
69    }
70
71    /// Get information about all exports of this package with the given MAST root digest
72    pub fn get_exports_by_digest(
73        &self,
74        digest: &Word,
75    ) -> impl Iterator<Item = &PackageExport> + '_ {
76        let digest = *digest;
77        self.exports.values().filter(move |export| export.digest == digest)
78    }
79}
80
81/// A procedure exported by a package, along with its digest and signature (will be added after
82/// MASM type attributes are implemented).
83#[derive(Clone, PartialEq, Eq)]
84#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
85#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
86#[cfg_attr(all(feature = "arbitrary", test), miden_test_serde_macros::serde_test)]
87pub struct PackageExport {
88    /// The fully-qualified name of the procedure exported by this package.
89    pub name: QualifiedProcedureName,
90    /// The digest of the procedure exported by this package.
91    #[cfg_attr(feature = "arbitrary", proptest(value = "Word::default()"))]
92    pub digest: Word,
93    /// The type signature of the exported procedure.
94    #[cfg_attr(feature = "arbitrary", proptest(value = "None"))]
95    #[cfg_attr(feature = "serde", serde(default))]
96    pub signature: Option<FunctionType>,
97    /// Attributes attached to the exported procedure.
98    #[cfg_attr(feature = "arbitrary", proptest(value = "AttributeSet::default()"))]
99    #[cfg_attr(feature = "serde", serde(default))]
100    pub attributes: AttributeSet,
101}
102
103impl fmt::Debug for PackageExport {
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        let Self { name, digest, signature, attributes } = self;
106        f.debug_struct("PackageExport")
107            .field("name", &format_args!("{name}"))
108            .field("digest", &format_args!("{}", DisplayHex::new(&digest.as_bytes())))
109            .field("signature", signature)
110            .field("attributes", attributes)
111            .finish()
112    }
113}