1#[derive(
3 serde::Serialize,
4 Clone,
5 Copy,
6 strum::EnumIter,
7 strum::EnumString,
8 strum::Display,
9 Debug,
10 PartialEq,
11 serde::Deserialize,
12)]
13#[strum(serialize_all = "kebab_case")]
14#[serde(rename_all = "kebab-case")]
15#[repr(u64)]
16pub enum KnownMagic {
17 RainMetaDocumentV1 = 0xff0a89c674ee7874,
21
22 OpMetaV1 = 0xffe5282f43e495b4,
24 DotrainV1 = 0xffdac2f2f37be894,
26 RainlangV1 = 0xff1c198cec3b48a7,
28 SolidityAbiV2 = 0xffe5ffb4a3ff2cde,
30 AuthoringMetaV1 = 0xffe9e3a02ca8e235,
32 AuthoringMetaV2 = 0xff52fe42f1a05093,
34 InterpreterCallerMetaV1 = 0xffc21bbf86cc199b,
36 ExpressionDeployerV2BytecodeV1 = 0xffdb988a8cd04d32,
38 RainlangSourceV1 = 0xff13109e41336ff2,
40 AddressList = 0xffb2637608c09e38,
42 DotrainSourceV1 = 0xffa15ef0fc437099,
44 OrderBuilderStateV1 = 0xffda7b2fb167c286,
46 RaindexSignedContextOracleV1 = 0xff7a1507ba4419ca,
50 WebDataV1 = 0xff5dcce9b571ba42,
52 OaSchema = 0xffa8e8a9b9cf4a31,
54 OaHashList = 0xff9fae3cc645f463,
56 OaStructure = 0xffc47a6299e8a911,
58 OaTokenImage = 0xff8cd2927c8c86cb,
60 OaTokenCredentialLinks = 0xffbc38eb14ad2209,
62}
63
64impl KnownMagic {
65 pub fn to_prefix_bytes(&self) -> [u8; 8] {
66 (*self as u64).to_be_bytes()
68 }
69}
70
71impl TryFrom<u64> for KnownMagic {
72 type Error = crate::error::Error;
73 fn try_from(value: u64) -> Result<Self, Self::Error> {
74 match value {
75 v if v == KnownMagic::OpMetaV1 as u64 => Ok(KnownMagic::OpMetaV1),
76 v if v == KnownMagic::DotrainV1 as u64 => Ok(KnownMagic::DotrainV1),
77 v if v == KnownMagic::RainlangV1 as u64 => Ok(KnownMagic::RainlangV1),
78 v if v == KnownMagic::SolidityAbiV2 as u64 => Ok(KnownMagic::SolidityAbiV2),
79 v if v == KnownMagic::AuthoringMetaV1 as u64 => Ok(KnownMagic::AuthoringMetaV1),
80 v if v == KnownMagic::AuthoringMetaV2 as u64 => Ok(KnownMagic::AuthoringMetaV2),
81 v if v == KnownMagic::AddressList as u64 => Ok(KnownMagic::AddressList),
82 v if v == KnownMagic::InterpreterCallerMetaV1 as u64 => {
89 Ok(KnownMagic::InterpreterCallerMetaV1)
90 }
91 v if v == KnownMagic::ExpressionDeployerV2BytecodeV1 as u64 => {
92 Ok(KnownMagic::ExpressionDeployerV2BytecodeV1)
93 }
94 v if v == KnownMagic::RainlangSourceV1 as u64 => Ok(KnownMagic::RainlangSourceV1),
95 v if v == KnownMagic::DotrainSourceV1 as u64 => Ok(KnownMagic::DotrainSourceV1),
96 v if v == KnownMagic::OrderBuilderStateV1 as u64 => Ok(KnownMagic::OrderBuilderStateV1),
97 v if v == KnownMagic::RaindexSignedContextOracleV1 as u64 => {
98 Ok(KnownMagic::RaindexSignedContextOracleV1)
99 }
100 v if v == KnownMagic::WebDataV1 as u64 => Ok(KnownMagic::WebDataV1),
101 v if v == KnownMagic::OaSchema as u64 => Ok(KnownMagic::OaSchema),
102 v if v == KnownMagic::OaHashList as u64 => Ok(KnownMagic::OaHashList),
103 v if v == KnownMagic::OaStructure as u64 => Ok(KnownMagic::OaStructure),
104 v if v == KnownMagic::OaTokenImage as u64 => Ok(KnownMagic::OaTokenImage),
105 v if v == KnownMagic::OaTokenCredentialLinks as u64 => {
106 Ok(KnownMagic::OaTokenCredentialLinks)
107 }
108 _ => Err(crate::error::Error::UnknownMagic),
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::KnownMagic;
116 use alloy::primitives::hex;
117
118 #[test]
119 fn test_rain_meta_document_v1() {
120 let magic_number = KnownMagic::RainMetaDocumentV1;
121 let magic_number_after_prefix = magic_number.to_prefix_bytes();
122
123 assert_eq!(hex::encode(magic_number_after_prefix), "ff0a89c674ee7874");
124 }
125
126 #[test]
127 fn test_solidity_abi_v2() {
128 let magic_number = KnownMagic::SolidityAbiV2;
129 let magic_number_after_prefix = magic_number.to_prefix_bytes();
130
131 assert_eq!(hex::encode(magic_number_after_prefix), "ffe5ffb4a3ff2cde");
132 }
133
134 #[test]
135 fn test_op_meta_v1() {
136 let magic_number = KnownMagic::OpMetaV1;
137 let magic_number_after_prefix = magic_number.to_prefix_bytes();
138
139 assert_eq!(hex::encode(magic_number_after_prefix), "ffe5282f43e495b4");
140 }
141
142 #[test]
143 fn test_interpreter_caller_meta_v1() {
144 let magic_number = KnownMagic::InterpreterCallerMetaV1;
145 let magic_number_after_prefix = magic_number.to_prefix_bytes();
146
147 assert_eq!(hex::encode(magic_number_after_prefix), "ffc21bbf86cc199b");
148 }
149
150 #[test]
151 fn test_authoring_meta_v1() {
152 let magic_number = KnownMagic::AuthoringMetaV1;
153 let magic_number_after_prefix = magic_number.to_prefix_bytes();
154
155 assert_eq!(hex::encode(magic_number_after_prefix), "ffe9e3a02ca8e235");
156 }
157
158 #[test]
159 fn test_authoring_meta_v2() {
160 let magic_number = KnownMagic::AuthoringMetaV2;
161 let magic_number_after_prefix = magic_number.to_prefix_bytes();
162
163 assert_eq!(hex::encode(magic_number_after_prefix), "ff52fe42f1a05093");
164 }
165
166 #[test]
167 fn test_dotrain_meta_v1() {
168 let magic_number = KnownMagic::DotrainV1;
169 let magic_number_after_prefix = magic_number.to_prefix_bytes();
170
171 assert_eq!(hex::encode(magic_number_after_prefix), "ffdac2f2f37be894");
172 }
173
174 #[test]
175 fn test_rainlang_meta_v1() {
176 let magic_number = KnownMagic::RainlangV1;
177 let magic_number_after_prefix = magic_number.to_prefix_bytes();
178
179 assert_eq!(hex::encode(magic_number_after_prefix), "ff1c198cec3b48a7");
180 }
181
182 #[test]
183 fn test_expression_deployer_v2_bytecode_meta_v1() {
184 let magic_number = KnownMagic::ExpressionDeployerV2BytecodeV1;
185 let magic_number_after_prefix = magic_number.to_prefix_bytes();
186
187 assert_eq!(hex::encode(magic_number_after_prefix), "ffdb988a8cd04d32");
188 }
189
190 #[test]
191 fn test_rainlang_source_meta_v1() {
192 let magic_number = KnownMagic::RainlangSourceV1;
193 let magic_number_after_prefix = magic_number.to_prefix_bytes();
194
195 assert_eq!(hex::encode(magic_number_after_prefix), "ff13109e41336ff2");
196 }
197
198 #[test]
199 fn test_dotrain_source_meta_v1() {
200 let magic_number = KnownMagic::DotrainSourceV1;
201 let magic_number_after_prefix = magic_number.to_prefix_bytes();
202
203 assert_eq!(hex::encode(magic_number_after_prefix), "ffa15ef0fc437099");
204 }
205
206 #[test]
207 fn test_dotrain_instance_meta_v1() {
208 let magic_number = KnownMagic::OrderBuilderStateV1;
209 let magic_number_after_prefix = magic_number.to_prefix_bytes();
210
211 assert_eq!(hex::encode(magic_number_after_prefix), "ffda7b2fb167c286");
212 }
213
214 #[test]
215 fn test_signed_context_oracle_v1() {
216 let magic_number = KnownMagic::RaindexSignedContextOracleV1;
217 let magic_number_after_prefix = magic_number.to_prefix_bytes();
218
219 assert_eq!(hex::encode(magic_number_after_prefix), "ff7a1507ba4419ca");
220 }
221
222 #[test]
223 fn test_signed_context_oracle_v1_roundtrip() {
224 let magic_number = KnownMagic::RaindexSignedContextOracleV1;
225 let from_u64 = KnownMagic::try_from(magic_number as u64).unwrap();
226 assert_eq!(magic_number, from_u64);
227 }
228
229 #[test]
230 fn test_web_data_v1() {
231 let magic_number = KnownMagic::WebDataV1;
232 let magic_number_after_prefix = magic_number.to_prefix_bytes();
233
234 assert_eq!(hex::encode(magic_number_after_prefix), "ff5dcce9b571ba42");
235 }
236
237 #[test]
238 fn test_oa_schema() {
239 let magic_number = KnownMagic::OaSchema;
240 let magic_number_after_prefix = magic_number.to_prefix_bytes();
241
242 assert_eq!(hex::encode(magic_number_after_prefix), "ffa8e8a9b9cf4a31");
243 }
244
245 #[test]
246 fn test_oa_hash_list() {
247 let magic_number = KnownMagic::OaHashList;
248 let magic_number_after_prefix = magic_number.to_prefix_bytes();
249
250 assert_eq!(hex::encode(magic_number_after_prefix), "ff9fae3cc645f463");
251 }
252
253 #[test]
254 fn test_oa_structure() {
255 let magic_number = KnownMagic::OaStructure;
256 let magic_number_after_prefix = magic_number.to_prefix_bytes();
257
258 assert_eq!(hex::encode(magic_number_after_prefix), "ffc47a6299e8a911");
259 }
260
261 #[test]
262 fn test_oa_token_image() {
263 let magic_number = KnownMagic::OaTokenImage;
264 let magic_number_after_prefix = magic_number.to_prefix_bytes();
265
266 assert_eq!(hex::encode(magic_number_after_prefix), "ff8cd2927c8c86cb");
267 }
268
269 #[test]
270 fn test_oa_token_credential_links() {
271 let magic_number = KnownMagic::OaTokenCredentialLinks;
272 let magic_number_after_prefix = magic_number.to_prefix_bytes();
273
274 assert_eq!(hex::encode(magic_number_after_prefix), "ffbc38eb14ad2209");
275 }
276
277 #[test]
278 fn test_oa_magics_roundtrip() {
279 for magic_number in [
280 KnownMagic::OaSchema,
281 KnownMagic::OaHashList,
282 KnownMagic::OaStructure,
283 KnownMagic::OaTokenImage,
284 KnownMagic::OaTokenCredentialLinks,
285 ] {
286 let from_u64 = KnownMagic::try_from(magic_number as u64).unwrap();
287 assert_eq!(magic_number, from_u64);
288 }
289 }
290
291 #[test]
292 fn test_address_list() {
293 let magic_number = KnownMagic::AddressList;
294 let magic_number_after_prefix = magic_number.to_prefix_bytes();
295
296 assert_eq!(hex::encode(magic_number_after_prefix), "ffb2637608c09e38");
297 }
298
299 #[test]
303 fn test_all_discriminants_pinned() {
304 use strum::IntoEnumIterator;
305 let expected: [(KnownMagic, &str); 20] = [
306 (KnownMagic::RainMetaDocumentV1, "ff0a89c674ee7874"),
307 (KnownMagic::OpMetaV1, "ffe5282f43e495b4"),
308 (KnownMagic::DotrainV1, "ffdac2f2f37be894"),
309 (KnownMagic::RainlangV1, "ff1c198cec3b48a7"),
310 (KnownMagic::SolidityAbiV2, "ffe5ffb4a3ff2cde"),
311 (KnownMagic::AuthoringMetaV1, "ffe9e3a02ca8e235"),
312 (KnownMagic::AuthoringMetaV2, "ff52fe42f1a05093"),
313 (KnownMagic::InterpreterCallerMetaV1, "ffc21bbf86cc199b"),
314 (
315 KnownMagic::ExpressionDeployerV2BytecodeV1,
316 "ffdb988a8cd04d32",
317 ),
318 (KnownMagic::RainlangSourceV1, "ff13109e41336ff2"),
319 (KnownMagic::AddressList, "ffb2637608c09e38"),
320 (KnownMagic::DotrainSourceV1, "ffa15ef0fc437099"),
321 (KnownMagic::OrderBuilderStateV1, "ffda7b2fb167c286"),
322 (KnownMagic::RaindexSignedContextOracleV1, "ff7a1507ba4419ca"),
323 (KnownMagic::WebDataV1, "ff5dcce9b571ba42"),
324 (KnownMagic::OaSchema, "ffa8e8a9b9cf4a31"),
325 (KnownMagic::OaHashList, "ff9fae3cc645f463"),
326 (KnownMagic::OaStructure, "ffc47a6299e8a911"),
327 (KnownMagic::OaTokenImage, "ff8cd2927c8c86cb"),
328 (KnownMagic::OaTokenCredentialLinks, "ffbc38eb14ad2209"),
329 ];
330 assert_eq!(expected.len(), KnownMagic::iter().count());
332 for (magic, hex_str) in expected {
333 assert_eq!(hex::encode(magic.to_prefix_bytes()), hex_str, "{:?}", magic);
334 }
335 }
336
337 #[test]
340 fn test_all_prefixes_start_with_0xff() {
341 use strum::IntoEnumIterator;
342 for magic in KnownMagic::iter() {
343 assert_eq!(magic.to_prefix_bytes()[0], 0xff, "{:?}", magic);
344 }
345 }
346
347 #[test]
349 fn test_try_from_u64_roundtrip_all() {
350 use strum::IntoEnumIterator;
351 for magic in KnownMagic::iter() {
352 if magic == KnownMagic::RainMetaDocumentV1 {
355 continue;
356 }
357 let from_u64 = KnownMagic::try_from(magic as u64).unwrap();
358 assert_eq!(magic, from_u64);
359 }
360 }
361
362 #[test]
365 fn test_try_from_u64_rejects_the_document_magic() {
366 assert!(matches!(
367 KnownMagic::try_from(KnownMagic::RainMetaDocumentV1 as u64),
368 Err(crate::error::Error::UnknownMagic)
369 ));
370 }
371
372 #[test]
374 fn test_try_from_u64_unknown_magic() {
375 for unknown in [0u64, 1, 0xdeadbeef, 0xff0a89c674ee7875, u64::MAX] {
376 assert!(matches!(
377 KnownMagic::try_from(unknown),
378 Err(crate::error::Error::UnknownMagic)
379 ));
380 }
381 }
382
383 #[test]
386 fn test_strum_kebab_case_parse_display() {
387 use std::str::FromStr;
388 let cases: [(KnownMagic, &str); 20] = [
389 (KnownMagic::RainMetaDocumentV1, "rain-meta-document-v1"),
390 (KnownMagic::OpMetaV1, "op-meta-v1"),
391 (KnownMagic::DotrainV1, "dotrain-v1"),
392 (KnownMagic::RainlangV1, "rainlang-v1"),
393 (KnownMagic::SolidityAbiV2, "solidity-abi-v2"),
394 (KnownMagic::AuthoringMetaV1, "authoring-meta-v1"),
395 (KnownMagic::AuthoringMetaV2, "authoring-meta-v2"),
396 (
397 KnownMagic::InterpreterCallerMetaV1,
398 "interpreter-caller-meta-v1",
399 ),
400 (
401 KnownMagic::ExpressionDeployerV2BytecodeV1,
402 "expression-deployer-v2-bytecode-v1",
403 ),
404 (KnownMagic::RainlangSourceV1, "rainlang-source-v1"),
405 (KnownMagic::AddressList, "address-list"),
406 (KnownMagic::DotrainSourceV1, "dotrain-source-v1"),
407 (KnownMagic::OrderBuilderStateV1, "order-builder-state-v1"),
408 (
409 KnownMagic::RaindexSignedContextOracleV1,
410 "raindex-signed-context-oracle-v1",
411 ),
412 (KnownMagic::WebDataV1, "web-data-v1"),
413 (KnownMagic::OaSchema, "oa-schema"),
414 (KnownMagic::OaHashList, "oa-hash-list"),
415 (KnownMagic::OaStructure, "oa-structure"),
416 (KnownMagic::OaTokenImage, "oa-token-image"),
417 (
418 KnownMagic::OaTokenCredentialLinks,
419 "oa-token-credential-links",
420 ),
421 ];
422 for (magic, name) in cases {
423 assert_eq!(magic.to_string(), name, "{:?}", magic);
424 assert_eq!(KnownMagic::from_str(name).unwrap(), magic, "{}", name);
425 }
426 }
427
428 #[test]
431 fn test_serde_kebab_case_roundtrip() {
432 use strum::IntoEnumIterator;
433 for magic in KnownMagic::iter() {
434 let json = serde_json::to_string(&magic).unwrap();
435 assert_eq!(json, format!("\"{}\"", magic), "{:?}", magic);
436 let back: KnownMagic = serde_json::from_str(&json).unwrap();
437 assert_eq!(back, magic);
438 }
439 }
440}