2个版本
0.1.1 | 2022年10月22日 |
---|---|
0.1.0 | 2022年10月22日 |
#1726 in 编码
47KB
1K SLoC
为libipld提供的原始CBOR编解码器
与dag-cbor不同,dag-cbor是有效CBOR的一个子集,而这个crate支持任何CBOR,并且额外支持标签42用于ipld链接。
如果你想要与dag-pb或dag-json进行互操作,dag-cbor是不错的选择,但如果你只需要带有标签的CBOR,这个crate就是为你准备的。
非字符串键
dag-cbor不允许使用非字符串键的字典,但这个crate允许这样做,这对于数据建模非常有用。例如,你可能有整数键的映射,或者你想要编码的结构化键,而不必将它们编码为字符串或使用2元组的列表。
这个crate允许序列化任何映射
impl<K: Encode<CborCodec>, T: Encode<CborCodec> + 'static> Encode<CborCodec> for BTreeMap<K, T> {
IPLD dag-cbor只能序列化具有字符串键的映射
impl<T: Encode<DagCbor> + 'static> Encode<DagCbor> for BTreeMap<String, T> {
映射键排序顺序
另一个不同之处在于,dag-cbor编解码器在编解码时会花费一些时间对数据进行规范化(例如,按映射键排序),而这个编解码器不会这样做。这可能会带来一些性能优势。
在这个crate中,映射数据按照其在映射中的顺序直接写入,而不创建临时对象
impl<K: Encode<RawCborCodec>, T: Encode<RawCborCodec> + 'static> Encode<RawCborCodec> for BTreeMap<K, T> {
fn encode<W: Write>(&self, c: RawCborCodec, w: &mut W) -> Result<()> {
write_u64(w, 5, self.len() as u64)?;
for (k, v) in self {
k.encode(c, w)?;
v.encode(c, w)?;
}
Ok(())
}
}
在IPLD dag-cbor crate中,映射数据首先存储在一个vec中,然后按长度排序
impl<T: Encode<DagCbor> + 'static> Encode<DagCbor> for BTreeMap<String, T> {
fn encode<W: Write>(&self, c: DagCbor, w: &mut W) -> Result<()> {
write_u64(w, MajorKind::Map, self.len() as u64)?;
// CBOR RFC-7049 specifies a canonical sort order, where keys are sorted by length first.
// This was later revised with RFC-8949, but we need to stick to the original order to stay
// compatible with existing data.
let mut cbor_order = Vec::from_iter(self);
cbor_order.sort_unstable_by(|&(key_a, _), &(key_b, _)| {
match key_a.len().cmp(&key_b.len()) {
Ordering::Greater => Ordering::Greater,
Ordering::Less => Ordering::Less,
Ordering::Equal => key_a.cmp(key_b),
}
});
for (k, v) in cbor_order {
k.encode(c, w)?;
v.encode(c, w)?;
}
Ok(())
}
}
依赖项
~1.2–2MB
~39K SLoC