1use crate::awl::{AWL_DOCUMENT_PREFIX, AWL_SCHEMA_PREFIX};
4
5#[derive(thiserror::Error, Debug)]
7pub enum PackageError {
8 #[error("failed to read .aion ZIP archive: {0}")]
10 ArchiveRead(#[from] zip::result::ZipError),
11
12 #[error("missing required manifest.json entry")]
14 MissingManifest,
15
16 #[error("missing required contract record for .v4 package identity")]
18 MissingContractRecord,
19
20 #[error(
22 "module `{module}` uses an engine-reserved namespace and must not ship as package bytecode"
23 )]
24 ReservedModuleName {
25 module: String,
27 },
28
29 #[error("failed to write .aion ZIP archive: {0}")]
31 ArchiveWrite(zip::result::ZipError),
32
33 #[error("failed to write .aion archive bytes: {source}")]
35 ArchiveWriteIo {
36 source: std::io::Error,
38 },
39
40 #[error("failed to parse manifest.json: {source}")]
42 ManifestParse {
43 source: serde_json::Error,
45 },
46
47 #[error("failed to serialise manifest.json: {source}")]
49 ManifestSerialise {
50 source: serde_json::Error,
52 },
53
54 #[error("failed to parse contract.json: {source}")]
56 ContractParse {
57 source: serde_json::Error,
59 },
60
61 #[error("failed to serialise contract.json: {source}")]
63 ContractSerialise {
64 source: serde_json::Error,
66 },
67
68 #[error("contract.json declared-command entry rejected: {detail}")]
73 ContractPriorFormMalformed {
74 detail: String,
76 },
77
78 #[error("unknown .aion format_version {found}")]
80 UnknownFormatVersion {
81 found: u32,
83 },
84
85 #[error("missing entry module `{module}` in beam set")]
87 MissingEntryModule {
88 module: String,
90 },
91
92 #[error("package integrity mismatch: expected version `{expected}`, computed `{computed}`")]
94 IntegrityMismatch {
95 expected: String,
97 computed: String,
99 },
100
101 #[error("malformed beam entry `{entry}`")]
103 MalformedBeamEntry {
104 entry: String,
106 },
107
108 #[error("malformed AWL source entry `{entry}`")]
111 MalformedAwlEntry {
112 entry: String,
114 },
115
116 #[error("archived AWL document `{entry}` is not valid UTF-8: {source}")]
118 AwlDocumentNotUtf8 {
119 entry: String,
121 source: std::string::FromUtf8Error,
123 },
124
125 #[error("archive carries `{AWL_SCHEMA_PREFIX}` entries but no `{AWL_DOCUMENT_PREFIX}` entry")]
128 MissingAwlDocument,
129
130 #[error(
132 "archive contents inflate past the extraction limit of {limit} bytes; refusing to extract further"
133 )]
134 InflatedSizeExceeded {
135 limit: u64,
137 },
138}
139
140#[cfg(test)]
141mod tests {
142 use super::PackageError;
143
144 fn assert_send_sync<T: Send + Sync>() {}
145
146 #[test]
147 fn package_error_is_send_and_sync() {
148 assert_send_sync::<PackageError>();
149 }
150
151 #[test]
152 fn display_messages_name_the_failed_condition() {
153 assert_eq!(
154 PackageError::MissingManifest.to_string(),
155 "missing required manifest.json entry"
156 );
157 assert_eq!(
158 PackageError::ArchiveWriteIo {
159 source: std::io::Error::other("disk full"),
160 }
161 .to_string(),
162 "failed to write .aion archive bytes: disk full"
163 );
164 assert_eq!(
165 PackageError::UnknownFormatVersion { found: 99 }.to_string(),
166 "unknown .aion format_version 99"
167 );
168 assert_eq!(
169 PackageError::MissingEntryModule {
170 module: "workflow/main".to_owned(),
171 }
172 .to_string(),
173 "missing entry module `workflow/main` in beam set"
174 );
175 assert_eq!(
176 PackageError::IntegrityMismatch {
177 expected: "expected".to_owned(),
178 computed: "computed".to_owned(),
179 }
180 .to_string(),
181 "package integrity mismatch: expected version `expected`, computed `computed`"
182 );
183 assert_eq!(
184 PackageError::MalformedBeamEntry {
185 entry: "beam/workflow.beam".to_owned(),
186 }
187 .to_string(),
188 "malformed beam entry `beam/workflow.beam`"
189 );
190 assert_eq!(
191 PackageError::InflatedSizeExceeded { limit: 1024 }.to_string(),
192 "archive contents inflate past the extraction limit of 1024 bytes; refusing to extract further"
193 );
194 }
195}