Skip to main content

aion_package/
error.rs

1//! Error taxonomy for malformed `.aion` packages.
2
3/// Errors produced while validating or loading a `.aion` package.
4#[derive(thiserror::Error, Debug)]
5pub enum PackageError {
6    /// The archive could not be read as a ZIP container.
7    #[error("failed to read .aion ZIP archive: {0}")]
8    ArchiveRead(#[from] zip::result::ZipError),
9
10    /// The archive does not contain the required root manifest.
11    #[error("missing required manifest.json entry")]
12    MissingManifest,
13
14    /// A module uses a namespace owned by the engine's native NIF layer.
15    #[error(
16        "module `{module}` uses an engine-reserved namespace and must not ship as package bytecode"
17    )]
18    ReservedModuleName {
19        /// The offending logical module name.
20        module: String,
21    },
22
23    /// The archive could not be written as a ZIP container.
24    #[error("failed to write .aion ZIP archive: {0}")]
25    ArchiveWrite(zip::result::ZipError),
26
27    /// The archive target could not be written to the filesystem or memory buffer.
28    #[error("failed to write .aion archive bytes: {source}")]
29    ArchiveWriteIo {
30        /// I/O failure reported by the write target.
31        source: std::io::Error,
32    },
33
34    /// The manifest entry is present but is not valid manifest JSON.
35    #[error("failed to parse manifest.json: {source}")]
36    ManifestParse {
37        /// JSON parsing failure reported by `serde_json`.
38        source: serde_json::Error,
39    },
40
41    /// The manifest could not be serialised for writing into the archive.
42    #[error("failed to serialise manifest.json: {source}")]
43    ManifestSerialise {
44        /// JSON serialisation failure reported by `serde_json`.
45        source: serde_json::Error,
46    },
47
48    /// The manifest declares a format version this crate does not support.
49    #[error("unknown .aion format_version {found}")]
50    UnknownFormatVersion {
51        /// Unsupported format version found in the manifest.
52        found: u32,
53    },
54
55    /// The manifest entry module is not present in the beam set.
56    #[error("missing entry module `{module}` in beam set")]
57    MissingEntryModule {
58        /// Logical entry module named by the manifest.
59        module: String,
60    },
61
62    /// The manifest version does not match the hash recomputed from beams.
63    #[error("package integrity mismatch: expected version `{expected}`, computed `{computed}`")]
64    IntegrityMismatch {
65        /// Version claimed by the manifest.
66        expected: String,
67        /// Version recomputed from package beams.
68        computed: String,
69    },
70
71    /// A beam archive entry is malformed or ambiguous.
72    #[error("malformed beam entry `{entry}`")]
73    MalformedBeamEntry {
74        /// Archive entry or logical module name that failed validation.
75        entry: String,
76    },
77}
78
79#[cfg(test)]
80mod tests {
81    use super::PackageError;
82
83    fn assert_send_sync<T: Send + Sync>() {}
84
85    #[test]
86    fn package_error_is_send_and_sync() {
87        assert_send_sync::<PackageError>();
88    }
89
90    #[test]
91    fn display_messages_name_the_failed_condition() {
92        assert_eq!(
93            PackageError::MissingManifest.to_string(),
94            "missing required manifest.json entry"
95        );
96        assert_eq!(
97            PackageError::ArchiveWriteIo {
98                source: std::io::Error::other("disk full"),
99            }
100            .to_string(),
101            "failed to write .aion archive bytes: disk full"
102        );
103        assert_eq!(
104            PackageError::UnknownFormatVersion { found: 99 }.to_string(),
105            "unknown .aion format_version 99"
106        );
107        assert_eq!(
108            PackageError::MissingEntryModule {
109                module: "workflow/main".to_owned(),
110            }
111            .to_string(),
112            "missing entry module `workflow/main` in beam set"
113        );
114        assert_eq!(
115            PackageError::IntegrityMismatch {
116                expected: "expected".to_owned(),
117                computed: "computed".to_owned(),
118            }
119            .to_string(),
120            "package integrity mismatch: expected version `expected`, computed `computed`"
121        );
122        assert_eq!(
123            PackageError::MalformedBeamEntry {
124                entry: "beam/workflow.beam".to_owned(),
125            }
126            .to_string(),
127            "malformed beam entry `beam/workflow.beam`"
128        );
129    }
130}