#ipld #cbor #serialization #raw #codec #tags #key

libipld-raw-cbor

ipld原始CBOR编解码器

2个版本

0.1.1 2022年10月22日
0.1.0 2022年10月22日

#1726 in 编码

MIT/Apache

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