#cbor #binary-format #binary-representation #builder #binary-encoding #byte #binary-data

cbor-data

一个用于将 CBOR 作为动态形状数据的内存表示的库

28 个版本

0.8.17 2024 年 3 月 21 日
0.8.15 2022 年 11 月 3 日
0.8.3 2021 年 12 月 7 日
0.7.0 2021 年 11 月 28 日
0.2.1 2020 年 12 月 31 日

#421 in Rust 模式

Download history 1/week @ 2024-04-29 16/week @ 2024-05-06 25/week @ 2024-05-13 16/week @ 2024-05-20 23/week @ 2024-05-27 24/week @ 2024-06-03 13/week @ 2024-06-10 4/week @ 2024-06-17 25/week @ 2024-06-24 6/week @ 2024-07-08 20/week @ 2024-07-15 589/week @ 2024-07-29 7/week @ 2024-08-05

616 每月下载量
用于 8 个crate (6 直接)

MIT/Apache

215KB
5K SLoC

一个用于将 CBOR 作为动态形状数据的内存表示的库。

关于数据格式的详细信息,请参阅 RFC 8949。它通常用作数据交换格式,它模拟了 JSON 特性的超集,同时使用更紧凑的二进制表示。因此,数据表示更倾向于较小的内存大小,而不是最快的数据访问速度。

此库在使用此数据格式时提供了一系列权衡。您可以仅使用从线或文件中获得的位,无需支付除扫描字节以检查有效编码之外的初始开销,但然后在处理数据时可能造成分配。或者您可以在使用之前对位进行规范化,确保在数据中索引永远不会分配。

关于性能,您应该记住,数组和字典被编码为其元素的平坦并列组合,这意味着索引将必须解码项,在跳过它们时进行解码。

关于解析数据的解释,您可以选择检查特定的编码(通过在 ItemKind 上进行模式匹配)或检查更高级的 CborValue。在后一种情况下,许多二进制表示可能产生相同的结果,例如,当请求整数时,结果可能来自非最佳编码(如将 57 编写为 64 位值)或来自具有 570 非常数和 -1 指数的 BigDecimal。

示例

use cbor_data::{CborBuilder, Encoder, Writer, constants::*};

// create some nonsense CBOR item
let cbor = CborBuilder::new().encode_dict(|builder| {
    builder.with_key("name", |builder| builder.encode_str("Actyx"));
    builder.with_key("founded", |b| b.write_str("2016-02-11T13:00:00+01:00", [TAG_ISO8601]));
    builder.with_key("founders", |builder| builder.encode_array(|builder| {
        builder
            .encode_str("Oliver Stollmann")
            .encode_str("Maximilian Fischer")
            .encode_str("Roland Kuhn");
    }));
});

// access properties
use cbor_data::{PathElement, index_str, CborValue, value::Timestamp};
use std::borrow::Cow::{self, Borrowed};

let item = cbor.index(index_str("name")).unwrap();
assert_eq!(item.decode(), CborValue::Str(Borrowed("Actyx")));

// decoding references source bytes where possible, use make_static() to break ties
let decoded =
    cbor.index([PathElement::String(Borrowed("founded"))]).unwrap().decode().make_static();

// if you know what you’re looking for, you can use the as_* or to_* methods:
let ts = decoded.as_timestamp().unwrap();
assert_eq!(ts.unix_epoch(), 1_455_192_000);
assert_eq!(ts.nanos(), 0);
assert_eq!(ts.tz_sec_east(), 3600);

let item = cbor.index(index_str("founders[1]")).unwrap();
let name = item.decode().to_str();
// to_str() returns an Option<Cow<str>> to allow you to avoid allocations
// (i.e. this still takes the string’s bytes from `&cbor` in this case)
assert_eq!(name.as_ref().map(Cow::as_ref), Some("Maximilian Fischer"));

// access low-level encoding
use cbor_data::ItemKind;

let item = cbor.index(index_str("founded")).unwrap();
assert_eq!(item.tags().collect::<Vec<_>>(), [TAG_ISO8601]);
assert!(matches!(item.kind(), ItemKind::Str(s) if s == "2016-02-11T13:00:00+01:00"));

依赖关系

~0.5–6.5MB
~30K SLoC