I would love to have a single CBOR crate in Rust, supporting all there already is in @BurntSushi's rust-cbor, @pyfisch's serde_cbor, Toralf Wittner's cbor-codec and possibly more. Now CBOR in Rust seems to be fractured into these crates offering different tradeoffs:
-
rust-cbor supports encoding and decoding of generic
cbor::Cborvalues (with CBOR tags) and anything implementingrustc_serialize::De/Encodable. Also, it implementsToJsonandToCborfor the generic valuescbor::Cbor. However, rustc_serialize has been deprecated for some time now. -
serde_cbor encodes and decodes anything with
serde::De/Serialize, has genericserde_cbor::Value(without CBOR tag support) and can serialize intoserde_cbor::Value(in addition to aWriter). Closest to what I want but no longer maintained by the author. -
cbor-codec encodes and decodes to/from its generic
cbor::value::Valuetype. Also has "direct" en/decoding, but only for primitive types. Has a crate name collision withcborabove. EDIT: Realized that it does not support rustc_serialize.
As I wrote, I would love to have a single polished crate, either called cbor (@BurntSushi offered to include it into his crate with a version bump) or serde_cbor, using SerDe with most of the features of the current crates, and I would be happy to pour some time and care into it. Most or all of the code is already out there anyway. However, I would like to see clearly where we are and what others (for example @BurntSushi, @pyfisch, @oli_obk, @erickt and @dtolnay) think or plan first. Let me know!
Namely I would like to have a generic cbor::Value type (with tags and possibly rich key types), de/serialize types based on SerDe to/from binary and cbor::Value, convert cbor::Value to/from Json. For custom types and CBOR tags see below, but I would be also happy to do with limited tag support for now (e.g. only having them in cbor::Value). Another nice feature woud be to encode structs without field names (i.e. as tuples) to save bytes and time in exchange for portability, but that is just another feature.
CBOR tags
A bit of discussion on CBOR tags: Not the main point of the thread but I feel like we should not neglect it.
There has been some discussion on how to encode specific types with specific encoders. For example, timestamp may be encoded just as i64 (as in JSON and elsewhere) or it may be explicitely tagged with tag 1 as in CBOR RFC 2.4.1.
In general, we would need a mechanism in serde to specialize the type de/encoding implementation for certain formats, this was already discussed here and here. As I understood it, when we have specialization in rustc, one way to do it would be to have serde use a parametric variant of Serialize, something along the lines of (a sketch):
trait SpecSerialize<S> where S: Serializer {
fn spec_serialize(&self, serializer: S) -> Result<S::Ok, S::Error>
}
// default SpecSerialize for any Serilizer
impl<T, S> SpecSerialize<S> for T where T: Serialize, S: Serializer {
default fn spec_serialize(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.serialize(serializer)
}
}
Then you could write a specialization e.g. for SystemTime and CBOR (again, a sketch):
impl SpecSerialize<CborSerializer> for std::time::SystemTime {
fn spec_serialize(&self, serializer: CborSerializer) -> Result<CborSerializer::Ok, CborSerializer::Error> {
serializer.write_tagged_u64(1 /*tag number*/, self.duration_since(UNIX_EPOCH).as_secs())
}
}
Another way was proposed here, but I am not sure it is ideal (how about having different tags in different formats, or not having a fixed set of tags/types per format? do we need to assume that all format-variations behave as some form of "tags" even for complex types?). However, I am not sure what is the current consensus in serde and would like to hear.
Note that, as of 2017-12, specialization is still not fully working on nightly for type parameters (see e.g. #38516).
I would argue that more work on CBOR support even without tags is already really useful and worth polishing it a bit. And quite likely, adding tags when serde supports specialization should be possible.