From d3ca2ff4ec32cb96b5f742ac48a4d09321ab5966 Mon Sep 17 00:00:00 2001 From: Beiri22 Date: Wed, 30 Aug 2023 17:11:21 +0200 Subject: Support CBOR binary serialization / deserialization (#2000) --- crates/typst-library/Cargo.toml | 1 + crates/typst-library/src/compute/data.rs | 66 ++++++++++++++++++++++++++++++++ crates/typst-library/src/compute/mod.rs | 1 + 3 files changed, 68 insertions(+) (limited to 'crates') diff --git a/crates/typst-library/Cargo.toml b/crates/typst-library/Cargo.toml index aa1de020..f4c5b1ed 100644 --- a/crates/typst-library/Cargo.toml +++ b/crates/typst-library/Cargo.toml @@ -34,6 +34,7 @@ kurbo = "0.9" lipsum = "0.9" log = "0.4" once_cell = "1" +ciborium = "0.2.1" roxmltree = "0.18" rustybuzz = "0.7" serde_json = "1" diff --git a/crates/typst-library/src/compute/data.rs b/crates/typst-library/src/compute/data.rs index cd28d61e..f20623ae 100644 --- a/crates/typst-library/src/compute/data.rs +++ b/crates/typst-library/src/compute/data.rs @@ -505,6 +505,72 @@ fn format_yaml_error(error: serde_yaml::Error) -> EcoString { eco_format!("failed to parse yaml file: {}", error.to_string().trim()) } +/// Reads structured data from a CBOR file. +/// +/// The file must contain a valid cbor serialization. Mappings will be +/// converted into Typst dictionaries, and sequences will be converted into +/// Typst arrays. Strings and booleans will be converted into the Typst +/// equivalents, null-values (`null`, `~` or empty ``) will be converted into +/// `{none}`, and numbers will be converted to floats or integers depending on +/// whether they are whole numbers. +/// +/// The function returns a dictionary or value or an array, depending on +/// the input. +/// +/// Display: CBOR +/// Category: data-loading +#[func] +#[scope( + scope.define("decode", cbor_decode_func()); + scope.define("encode", cbor_encode_func()); + scope +)] +pub fn cbor( + /// Path to a CBOR file. + path: Spanned, + /// The virtual machine. + vm: &mut Vm, +) -> SourceResult { + let Spanned { v: path, span } = path; + let id = vm.resolve_path(&path).at(span)?; + let data = vm.world().file(id).at(span)?; + cbor_decode(Spanned::new(data, span)) +} + +/// Reads structured data from CBOR bytes. +/// +/// Display: CBOR +/// Category: data-loading +#[func] +pub fn cbor_decode( + /// cbor data. + data: Spanned, +) -> SourceResult { + let Spanned { v: data, span } = data; + let value: Value = ciborium::from_reader(data.as_slice()) + .map_err(|e| eco_format!("failed to parse cbor: {e}")) + .at(span)?; + Ok(value) +} + +/// Encode structured data into CBOR bytes. +/// +/// Display: CBOR +/// Category: data-loading +#[func] +pub fn cbor_encode( + /// Value to be encoded. + value: Spanned, +) -> SourceResult { + let Spanned { v: value, span } = value; + + let mut res = Vec::new(); + ciborium::into_writer(&value, &mut res) + .map(|_| res.into()) + .map_err(|e| eco_format!("failed to encode value as cbor: {e}")) + .at(span) +} + /// Reads structured data from an XML file. /// /// The XML file is parsed into an array of dictionaries and strings. XML nodes diff --git a/crates/typst-library/src/compute/mod.rs b/crates/typst-library/src/compute/mod.rs index 599ac72f..ca95f7b7 100644 --- a/crates/typst-library/src/compute/mod.rs +++ b/crates/typst-library/src/compute/mod.rs @@ -38,6 +38,7 @@ pub(super) fn define(global: &mut Scope) { global.define("json", json_func()); global.define("toml", toml_func()); global.define("yaml", yaml_func()); + global.define("cbor", cbor_func()); global.define("xml", xml_func()); global.define("calc", calc::module()); global.define("plugin", plugin_func()); -- cgit v1.2.3