#data #representation #cbor #dynamically #in-memory #shaped #binary-representation

cbor-data-derive

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

1 个不稳定版本

0.8.15 2022年11月3日

#28 in #binary-representation


3 个crate中使用(通过 cbor-data

MIT/Apache

15KB
339 代码行

一个库,用于将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"));

依赖项

~1.5MB
~36K SLoC