numcodecs_wasm_host/
wit.rs

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