miden_mast_package/package/
manifest.rs1use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
2use core::fmt;
3
4use miden_assembly_syntax::ast::{
5 self, AttributeSet, Path,
6 types::{FunctionType, Type},
7};
8use miden_core::{Word, utils::DisplayHex};
9#[cfg(feature = "arbitrary")]
10use proptest::prelude::{Strategy, any};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14use crate::Dependency;
15
16#[derive(Debug, Default, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
23pub struct PackageManifest {
24 #[cfg_attr(
26 feature = "arbitrary",
27 proptest(
28 strategy = "proptest::collection::vec(any::<PackageExport>(), 1..10).prop_map(|exports| PackageManifest::new(exports).exports)"
29 )
30 )]
31 pub(super) exports: BTreeMap<Arc<Path>, PackageExport>,
32 pub(super) dependencies: Vec<Dependency>,
35}
36
37impl PackageManifest {
38 pub fn new(exports: impl IntoIterator<Item = PackageExport>) -> Self {
39 let exports = exports.into_iter().map(|export| (export.path(), export)).collect();
40 Self {
41 exports,
42 dependencies: Default::default(),
43 }
44 }
45
46 pub fn with_dependencies(mut self, dependencies: impl IntoIterator<Item = Dependency>) -> Self {
48 self.dependencies.extend(dependencies);
49 self
50 }
51
52 pub fn add_dependency(&mut self, dependency: Dependency) {
54 self.dependencies.push(dependency);
55 }
56
57 pub fn num_dependencies(&self) -> usize {
59 self.dependencies.len()
60 }
61
62 pub fn dependencies(&self) -> impl Iterator<Item = &Dependency> {
64 self.dependencies.iter()
65 }
66
67 pub fn num_exports(&self) -> usize {
69 self.exports.len()
70 }
71
72 pub fn exports(&self) -> impl Iterator<Item = &PackageExport> {
74 self.exports.values()
75 }
76
77 pub fn get_export(&self, name: impl AsRef<Path>) -> Option<&PackageExport> {
79 self.exports.get(name.as_ref())
80 }
81
82 pub fn get_procedures_by_digest(
85 &self,
86 digest: &Word,
87 ) -> impl Iterator<Item = &ProcedureExport> + '_ {
88 let digest = *digest;
89 self.exports.values().filter_map(move |export| match export {
90 PackageExport::Procedure(export) if export.digest == digest => Some(export),
91 PackageExport::Procedure(_) => None,
92 PackageExport::Constant(_) | PackageExport::Type(_) => None,
93 })
94 }
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
99#[repr(u8)]
100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
101#[cfg_attr(all(feature = "arbitrary", test), miden_test_serde_macros::serde_test)]
102pub enum PackageExport {
103 Procedure(ProcedureExport) = 1,
105 Constant(ConstantExport),
107 Type(TypeExport),
109}
110
111impl PackageExport {
112 pub fn path(&self) -> Arc<Path> {
114 match self {
115 Self::Procedure(export) => export.path.clone(),
116 Self::Constant(export) => export.path.clone(),
117 Self::Type(export) => export.path.clone(),
118 }
119 }
120
121 pub fn namespace(&self) -> &Path {
125 match self {
126 Self::Procedure(ProcedureExport { path, .. })
127 | Self::Constant(ConstantExport { path, .. })
128 | Self::Type(TypeExport { path, .. }) => path.parent().unwrap(),
129 }
130 }
131
132 pub fn name(&self) -> &str {
136 match self {
137 Self::Procedure(ProcedureExport { path, .. })
138 | Self::Constant(ConstantExport { path, .. })
139 | Self::Type(TypeExport { path, .. }) => path.last().unwrap(),
140 }
141 }
142
143 #[inline]
145 pub fn is_procedure(&self) -> bool {
146 matches!(self, Self::Procedure(_))
147 }
148
149 #[inline]
151 pub fn is_constant(&self) -> bool {
152 matches!(self, Self::Constant(_))
153 }
154
155 #[inline]
157 pub fn is_type(&self) -> bool {
158 matches!(self, Self::Type(_))
159 }
160
161 pub(crate) const fn tag(&self) -> u8 {
162 unsafe { *(self as *const Self).cast::<u8>() }
169 }
170}
171
172#[cfg(feature = "arbitrary")]
173impl proptest::arbitrary::Arbitrary for PackageExport {
174 type Parameters = ();
175
176 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
177 use proptest::{arbitrary::any, prop_oneof, strategy::Strategy};
178
179 prop_oneof![
180 any::<ProcedureExport>().prop_map(Self::Procedure),
181 any::<ConstantExport>().prop_map(Self::Constant),
182 any::<TypeExport>().prop_map(Self::Type),
183 ]
184 .boxed()
185 }
186
187 type Strategy = proptest::prelude::BoxedStrategy<Self>;
188}
189
190#[derive(Clone, PartialEq, Eq)]
192#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
194#[cfg_attr(all(feature = "arbitrary", test), miden_test_serde_macros::serde_test)]
195pub struct ProcedureExport {
196 #[cfg_attr(feature = "serde", serde(with = "miden_assembly_syntax::ast::path"))]
198 #[cfg_attr(
199 feature = "arbitrary",
200 proptest(strategy = "miden_assembly_syntax::arbitrary::path::bare_path_random_length(2)")
201 )]
202 pub path: Arc<Path>,
203 #[cfg_attr(feature = "arbitrary", proptest(value = "Word::default()"))]
205 pub digest: Word,
206 #[cfg_attr(feature = "arbitrary", proptest(value = "None"))]
208 #[cfg_attr(feature = "serde", serde(default))]
209 pub signature: Option<FunctionType>,
210 #[cfg_attr(feature = "arbitrary", proptest(value = "AttributeSet::default()"))]
212 #[cfg_attr(feature = "serde", serde(default))]
213 pub attributes: AttributeSet,
214}
215
216impl fmt::Debug for ProcedureExport {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 let Self { path, digest, signature, attributes } = self;
219 f.debug_struct("PackageExport")
220 .field("path", &format_args!("{path}"))
221 .field("digest", &format_args!("{}", DisplayHex::new(&digest.as_bytes())))
222 .field("signature", signature)
223 .field("attributes", attributes)
224 .finish()
225 }
226}
227
228#[derive(Clone, PartialEq, Eq)]
230#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
232#[cfg_attr(all(feature = "arbitrary", test), miden_test_serde_macros::serde_test)]
233pub struct ConstantExport {
234 #[cfg_attr(feature = "serde", serde(with = "miden_assembly_syntax::ast::path"))]
236 #[cfg_attr(
237 feature = "arbitrary",
238 proptest(
239 strategy = "miden_assembly_syntax::arbitrary::path::constant_path_random_length(1)"
240 )
241 )]
242 pub path: Arc<Path>,
243 pub value: ast::ConstantValue,
250}
251
252impl fmt::Debug for ConstantExport {
253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254 let Self { path, value } = self;
255 f.debug_struct("ConstantExport")
256 .field("path", &format_args!("{path}"))
257 .field("value", value)
258 .finish()
259 }
260}
261
262#[derive(Clone, PartialEq, Eq)]
264#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
266#[cfg_attr(all(feature = "arbitrary", test), miden_test_serde_macros::serde_test)]
267pub struct TypeExport {
268 #[cfg_attr(feature = "serde", serde(with = "miden_assembly_syntax::ast::path"))]
270 #[cfg_attr(
271 feature = "arbitrary",
272 proptest(
273 strategy = "miden_assembly_syntax::arbitrary::path::user_defined_type_path_random_length(1)"
274 )
275 )]
276 pub path: Arc<Path>,
277 #[cfg_attr(feature = "arbitrary", proptest(value = "Type::Felt"))]
279 pub ty: Type,
280}
281
282impl fmt::Debug for TypeExport {
283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284 let Self { path, ty } = self;
285 f.debug_struct("TypeExport")
286 .field("path", &format_args!("{path}"))
287 .field("ty", ty)
288 .finish()
289 }
290}