1 个不稳定版本
0.8.15 | 2022年11月3日 |
---|
#28 in #binary-representation
在 3 个crate中使用(通过 cbor-data)
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