use ciborium::de::Error;
use ecow::eco_format;
use typst_syntax::Spanned;
use crate::diag::{At, LoadError, LoadedWithin, SourceResult};
use crate::engine::Engine;
use crate::foundations::{Bytes, Value, func, scope};
use crate::loading::{DataSource, Load};
#[func(scope, title = "CBOR")]
pub fn cbor(
engine: &mut Engine,
source: Spanned<DataSource>,
) -> SourceResult<Value> {
let loaded = source.load(engine.world)?;
ciborium::from_reader(loaded.data.as_slice())
.map_err(format_cbor_error)
.within(&loaded)
}
fn format_cbor_error(error: Error<std::io::Error>) -> LoadError {
LoadError::binary(
"failed to parse CBOR",
typst_utils::display(|f| match &error {
Error::Io(e) => write!(f, "IO error: {e}"),
Error::Syntax(_) => f.write_str("syntax error"),
Error::Semantic(_, s) => f.write_str(s),
Error::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
}),
)
}
#[scope]
impl cbor {
#[func(title = "Encode CBOR")]
pub fn encode(
value: Spanned<Value>,
) -> SourceResult<Bytes> {
let Spanned { v: value, span } = value;
let mut res = Vec::new();
ciborium::into_writer(&value, &mut res)
.map(|_| Bytes::new(res))
.map_err(|err| eco_format!("failed to encode value as CBOR ({err})"))
.at(span)
}
}