miden_mast_package/package/
serialization.rs

1//! The serialization format of `Package` is as follows:
2//!
3//! #### Header
4//! - `MAGIC_PACKAGE`, a 4-byte tag, followed by a NUL-byte, i.e. `b"\0"`
5//! - `VERSION`, a 3-byte semantic version number, 1 byte for each component, i.e. MAJ.MIN.PATCH
6//!
7//! #### Metadata
8//! - `name` (`String`)
9//! - `version` (optional, [`miden_assembly_syntax::Version`] serialized as a `String`)
10//! - `description` (optional, `String`)
11//! - `kind` (`u8`, see [`crate::PackageKind`])
12//!
13//! #### Code
14//! - `mast` (see [`crate::MastArtifact`])
15//!
16//! #### Manifest
17//! - `manifest` (see [`crate::PackageManifest`])
18//!
19//! #### Custom Sections
20//! - `sections` (a vector of zero or more [`crate::Section`])
21
22use alloc::{
23    collections::BTreeMap,
24    format,
25    string::{String, ToString},
26    sync::Arc,
27    vec::Vec,
28};
29
30use miden_assembly_syntax::{
31    Library,
32    ast::{AttributeSet, PathBuf},
33    library::{FunctionTypeDeserializer, FunctionTypeSerializer},
34};
35use miden_core::{
36    Program, Word,
37    utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
38};
39
40use super::{ConstantExport, PackageKind, ProcedureExport, TypeExport};
41use crate::{Dependency, MastArtifact, Package, PackageExport, PackageManifest, Section};
42
43// CONSTANTS
44// ================================================================================================
45
46/// Magic string for detecting that a file is serialized [`Package`]
47const MAGIC_PACKAGE: &[u8; 5] = b"MASP\0";
48
49/// Magic string indicating a Program artifact.
50const MAGIC_PROGRAM: &[u8; 4] = b"PRG\0";
51
52/// Magic string indicating a Library artifact.
53const MAGIC_LIBRARY: &[u8; 4] = b"LIB\0";
54
55/// The format version.
56///
57/// If future modifications are made to this format, the version should be incremented by 1.
58const VERSION: [u8; 3] = [3, 0, 0];
59
60// PACKAGE SERIALIZATION/DESERIALIZATION
61// ================================================================================================
62
63impl Serializable for Package {
64    fn write_into<W: ByteWriter>(&self, target: &mut W) {
65        // Write magic & version
66        target.write_bytes(MAGIC_PACKAGE);
67        target.write_bytes(&VERSION);
68
69        // Write package name
70        self.name.write_into(target);
71
72        // Write package version
73        self.version.as_ref().map(|v| v.to_string()).write_into(target);
74
75        // Write package description
76        self.description.write_into(target);
77
78        // Write package kind
79        target.write_u8(self.kind.into());
80
81        // Write MAST artifact
82        self.mast.write_into(target);
83
84        // Write manifest
85        self.manifest.write_into(target);
86
87        // Write custom sections
88        target.write_usize(self.sections.len());
89        for section in self.sections.iter() {
90            section.write_into(target);
91        }
92    }
93}
94
95impl Deserializable for Package {
96    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
97        // Read and validate magic & version
98        let magic: [u8; 5] = source.read_array()?;
99        if magic != *MAGIC_PACKAGE {
100            return Err(DeserializationError::InvalidValue(format!(
101                "invalid magic bytes. Expected '{MAGIC_PACKAGE:?}', got '{magic:?}'"
102            )));
103        }
104
105        let version: [u8; 3] = source.read_array()?;
106        if version != VERSION {
107            return Err(DeserializationError::InvalidValue(format!(
108                "unsupported version. Got '{version:?}', but only '{VERSION:?}' is supported"
109            )));
110        }
111
112        // Read package name
113        let name = String::read_from(source)?;
114
115        // Read package version
116        let version = Option::<String>::read_from(source)?;
117        let version = match version {
118            Some(version) => Some(
119                crate::Version::parse(&version)
120                    .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?,
121            ),
122            None => None,
123        };
124
125        // Read package description
126        let description = Option::<String>::read_from(source)?;
127
128        // Read package kind
129        let kind_tag = source.read_u8()?;
130        let kind = PackageKind::try_from(kind_tag)
131            .map_err(|e| DeserializationError::InvalidValue(e.to_string()))?;
132
133        // Read MAST artifact
134        let mast = MastArtifact::read_from(source)?;
135
136        // Read manifest
137        let manifest = PackageManifest::read_from(source)?;
138
139        // Read custom sections
140        let num_sections = source.read_usize()?;
141        let mut sections = Vec::with_capacity(num_sections);
142        for _ in 0..num_sections {
143            let section = Section::read_from(source)?;
144            sections.push(section);
145        }
146
147        Ok(Self {
148            name,
149            version,
150            description,
151            kind,
152            mast,
153            manifest,
154            sections,
155        })
156    }
157}
158
159// MAST ARTIFACT SERIALIZATION/DESERIALIZATION
160// ================================================================================================
161
162impl Serializable for MastArtifact {
163    fn write_into<W: ByteWriter>(&self, target: &mut W) {
164        match self {
165            Self::Executable(program) => {
166                target.write_bytes(MAGIC_PROGRAM);
167                program.write_into(target);
168            },
169            Self::Library(library) => {
170                target.write_bytes(MAGIC_LIBRARY);
171                library.write_into(target);
172            },
173        }
174    }
175}
176
177impl Deserializable for MastArtifact {
178    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
179        let tag: [u8; 4] = source.read_array()?;
180
181        if &tag == MAGIC_PROGRAM {
182            Program::read_from(source).map(Arc::new).map(MastArtifact::Executable)
183        } else if &tag == MAGIC_LIBRARY {
184            Library::read_from(source).map(Arc::new).map(MastArtifact::Library)
185        } else {
186            Err(DeserializationError::InvalidValue(format!(
187                "invalid MAST artifact tag: {:?}",
188                &tag
189            )))
190        }
191    }
192}
193
194// PACKAGE MANIFEST SERIALIZATION/DESERIALIZATION
195// ================================================================================================
196
197#[cfg(feature = "serde")]
198impl serde::Serialize for PackageManifest {
199    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
200    where
201        S: serde::Serializer,
202    {
203        use miden_assembly_syntax::Path;
204        use serde::ser::SerializeStruct;
205
206        struct PackageExports<'a>(&'a BTreeMap<Arc<Path>, PackageExport>);
207
208        impl serde::Serialize for PackageExports<'_> {
209            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
210            where
211                S: serde::Serializer,
212            {
213                use serde::ser::SerializeSeq;
214
215                let mut serializer = serializer.serialize_seq(Some(self.0.len()))?;
216                for value in self.0.values() {
217                    serializer.serialize_element(value)?;
218                }
219                serializer.end()
220            }
221        }
222
223        let mut serializer = serializer.serialize_struct("PackageManifest", 2)?;
224        serializer.serialize_field("exports", &PackageExports(&self.exports))?;
225        serializer.serialize_field("dependencies", &self.dependencies)?;
226        serializer.end()
227    }
228}
229
230#[cfg(feature = "serde")]
231impl<'de> serde::Deserialize<'de> for PackageManifest {
232    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
233    where
234        D: serde::Deserializer<'de>,
235    {
236        #[derive(serde::Deserialize)]
237        #[serde(field_identifier, rename_all = "lowercase")]
238        enum Field {
239            Exports,
240            Dependencies,
241        }
242
243        struct PackageManifestVisitor;
244
245        impl<'de> serde::de::Visitor<'de> for PackageManifestVisitor {
246            type Value = PackageManifest;
247
248            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
249                formatter.write_str("struct PackageManifest")
250            }
251
252            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
253            where
254                A: serde::de::SeqAccess<'de>,
255            {
256                let exports = seq
257                    .next_element::<Vec<PackageExport>>()?
258                    .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
259                let dependencies = seq
260                    .next_element::<Vec<Dependency>>()?
261                    .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
262                Ok(PackageManifest::new(exports).with_dependencies(dependencies))
263            }
264
265            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
266            where
267                A: serde::de::MapAccess<'de>,
268            {
269                let mut exports = None;
270                let mut dependencies = None;
271                while let Some(key) = map.next_key()? {
272                    match key {
273                        Field::Exports => {
274                            if exports.is_some() {
275                                return Err(serde::de::Error::duplicate_field("exports"));
276                            }
277                            exports = Some(map.next_value::<Vec<PackageExport>>()?);
278                        },
279                        Field::Dependencies => {
280                            if dependencies.is_some() {
281                                return Err(serde::de::Error::duplicate_field("dependencies"));
282                            }
283                            dependencies = Some(map.next_value::<Vec<Dependency>>()?);
284                        },
285                    }
286                }
287                let exports = exports.ok_or_else(|| serde::de::Error::missing_field("exports"))?;
288                let dependencies =
289                    dependencies.ok_or_else(|| serde::de::Error::missing_field("dependencies"))?;
290                Ok(PackageManifest::new(exports).with_dependencies(dependencies))
291            }
292        }
293
294        deserializer.deserialize_struct(
295            "PackageManifest",
296            &["exports", "dependencies"],
297            PackageManifestVisitor,
298        )
299    }
300}
301
302impl Serializable for PackageManifest {
303    fn write_into<W: ByteWriter>(&self, target: &mut W) {
304        // Write exports
305        target.write_usize(self.num_exports());
306        for export in self.exports() {
307            export.write_into(target);
308        }
309
310        // Write dependencies
311        target.write_usize(self.num_dependencies());
312        for dep in self.dependencies() {
313            dep.write_into(target);
314        }
315    }
316}
317
318impl Deserializable for PackageManifest {
319    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
320        // Read exports
321        let exports_len = source.read_usize()?;
322        let mut exports = BTreeMap::new();
323        for _ in 0..exports_len {
324            let export = PackageExport::read_from(source)?;
325            exports.insert(export.path().clone(), export);
326        }
327
328        // Read dependencies
329        let deps_len = source.read_usize()?;
330        let mut dependencies = Vec::with_capacity(deps_len);
331        for _ in 0..deps_len {
332            dependencies.push(Dependency::read_from(source)?);
333        }
334
335        Ok(Self { exports, dependencies })
336    }
337}
338
339// PACKAGE EXPORT SERIALIZATION/DESERIALIZATION
340// ================================================================================================
341impl Serializable for PackageExport {
342    fn write_into<W: ByteWriter>(&self, target: &mut W) {
343        target.write_u8(self.tag());
344        match self {
345            Self::Procedure(export) => export.write_into(target),
346            Self::Constant(export) => export.write_into(target),
347            Self::Type(export) => export.write_into(target),
348        }
349    }
350}
351
352impl Deserializable for PackageExport {
353    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
354        match source.read_u8()? {
355            1 => ProcedureExport::read_from(source).map(Self::Procedure),
356            2 => ConstantExport::read_from(source).map(Self::Constant),
357            3 => TypeExport::read_from(source).map(Self::Type),
358            invalid => Err(DeserializationError::InvalidValue(format!(
359                "unexpected PackageExport tag: '{invalid}'"
360            ))),
361        }
362    }
363}
364
365impl Serializable for ProcedureExport {
366    fn write_into<W: ByteWriter>(&self, target: &mut W) {
367        self.path.write_into(target);
368        self.digest.write_into(target);
369        match self.signature.as_ref() {
370            Some(sig) => {
371                target.write_bool(true);
372                FunctionTypeSerializer(sig).write_into(target);
373            },
374            None => {
375                target.write_bool(false);
376            },
377        }
378        self.attributes.write_into(target);
379    }
380}
381
382impl Deserializable for ProcedureExport {
383    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
384        let path = PathBuf::read_from(source)?.into_boxed_path().into();
385        let digest = Word::read_from(source)?;
386        let signature = if source.read_bool()? {
387            Some(FunctionTypeDeserializer::read_from(source)?.0)
388        } else {
389            None
390        };
391        let attributes = AttributeSet::read_from(source)?;
392        Ok(Self { path, digest, signature, attributes })
393    }
394}
395
396impl Serializable for ConstantExport {
397    fn write_into<W: ByteWriter>(&self, target: &mut W) {
398        self.path.write_into(target);
399        self.value.write_into(target);
400    }
401}
402
403impl Deserializable for ConstantExport {
404    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
405        let path = PathBuf::read_from(source)?.into_boxed_path().into();
406        let value = miden_assembly_syntax::ast::ConstantValue::read_from(source)?;
407        Ok(Self { path, value })
408    }
409}
410
411impl Serializable for TypeExport {
412    fn write_into<W: ByteWriter>(&self, target: &mut W) {
413        use miden_assembly_syntax::library::TypeSerializer;
414
415        self.path.write_into(target);
416        TypeSerializer(&self.ty).write_into(target);
417    }
418}
419
420impl Deserializable for TypeExport {
421    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
422        use miden_assembly_syntax::library::TypeDeserializer;
423
424        let path = PathBuf::read_from(source)?.into_boxed_path().into();
425        let ty = TypeDeserializer::read_from(source)?.0;
426        Ok(Self { path, ty })
427    }
428}