numcodecs_wasm_host/
wit.rs1use std::sync::OnceLock;
2
3use semver::Version;
4use wasm_component_layer::{InterfaceIdentifier, PackageIdentifier, PackageName, Value};
5
6use crate::error::{CodecError, RuntimeError};
7
8#[non_exhaustive]
10pub struct NumcodecsWitInterfaces {
11 pub package: PackageIdentifier,
13 pub codec: InterfaceIdentifier,
15 pub registry: InterfaceIdentifier,
17 pub types: InterfaceIdentifier,
19}
20
21impl NumcodecsWitInterfaces {
22 #[must_use]
24 pub fn get() -> &'static Self {
25 static NUMCODECS_WIT_INTERFACES: OnceLock<NumcodecsWitInterfaces> = OnceLock::new();
26
27 NUMCODECS_WIT_INTERFACES.get_or_init(|| {
28 let package = PackageIdentifier::new(
29 PackageName::new("numcodecs", "abc"),
30 Some(Version::new(0, 1, 1)),
31 );
32
33 Self {
34 package: package.clone(),
35 codec: InterfaceIdentifier::new(package.clone(), "codec"),
36 registry: InterfaceIdentifier::new(package.clone(), "registry"),
37 types: InterfaceIdentifier::new(package, "types"),
38 }
39 })
40 }
41}
42
43pub fn guest_error_from_wasm(err: Option<&Value>) -> Result<CodecError, RuntimeError> {
44 let Some(Value::Record(record)) = err else {
45 return Err(RuntimeError::from(anyhow::anyhow!(
46 "unexpected err value {err:?}"
47 )));
48 };
49
50 let Some(Value::String(message)) = record.field("message") else {
51 return Err(RuntimeError::from(anyhow::anyhow!(
52 "numcodecs:abc/codec::error is missing the `message` field"
53 )));
54 };
55
56 let Some(Value::List(chain)) = record.field("chain") else {
57 return Err(RuntimeError::from(anyhow::anyhow!(
58 "numcodecs:abc/codec::error is missing the `chain` field"
59 )));
60 };
61
62 let Ok(chain) = chain
63 .iter()
64 .map(|msg| match msg {
65 Value::String(msg) => Ok(msg),
66 _ => Err(()),
67 })
68 .collect::<Result<Vec<_>, _>>()
69 else {
70 return Err(RuntimeError::from(anyhow::anyhow!(
71 "numcodecs:abc/codec::error chain contains unexpected non-string values: {chain:?}"
72 )));
73 };
74
75 Ok(CodecError::new(message, chain))
76}