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