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 codec: InterfaceIdentifier,
13}
14
15impl NumcodecsWitInterfaces {
16 #[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}