typst_library/loading/
cbor.rs

1use ecow::eco_format;
2use typst_syntax::Spanned;
3
4use crate::diag::{At, SourceResult};
5use crate::engine::Engine;
6use crate::foundations::{func, scope, Bytes, Value};
7use crate::loading::{DataSource, Load};
8
9/// Reads structured data from a CBOR file.
10///
11/// The file must contain a valid CBOR serialization. Mappings will be
12/// converted into Typst dictionaries, and sequences will be converted into
13/// Typst arrays. Strings and booleans will be converted into the Typst
14/// equivalents, null-values (`null`, `~` or empty ``) will be converted into
15/// `{none}`, and numbers will be converted to floats or integers depending on
16/// whether they are whole numbers.
17///
18/// Be aware that integers larger than 2<sup>63</sup>-1 will be converted to
19/// floating point numbers, which may result in an approximative value.
20#[func(scope, title = "CBOR")]
21pub fn cbor(
22    engine: &mut Engine,
23    /// A [path]($syntax/#paths) to a CBOR file or raw CBOR bytes.
24    source: Spanned<DataSource>,
25) -> SourceResult<Value> {
26    let data = source.load(engine.world)?;
27    ciborium::from_reader(data.as_slice())
28        .map_err(|err| eco_format!("failed to parse CBOR ({err})"))
29        .at(source.span)
30}
31
32#[scope]
33impl cbor {
34    /// Reads structured data from CBOR bytes.
35    #[func(title = "Decode CBOR")]
36    #[deprecated = "`cbor.decode` is deprecated, directly pass bytes to `cbor` instead"]
37    pub fn decode(
38        engine: &mut Engine,
39        /// CBOR data.
40        data: Spanned<Bytes>,
41    ) -> SourceResult<Value> {
42        cbor(engine, data.map(DataSource::Bytes))
43    }
44
45    /// Encode structured data into CBOR bytes.
46    #[func(title = "Encode CBOR")]
47    pub fn encode(
48        /// Value to be encoded.
49        value: Spanned<Value>,
50    ) -> SourceResult<Bytes> {
51        let Spanned { v: value, span } = value;
52        let mut res = Vec::new();
53        ciborium::into_writer(&value, &mut res)
54            .map(|_| Bytes::new(res))
55            .map_err(|err| eco_format!("failed to encode value as CBOR ({err})"))
56            .at(span)
57    }
58}