[−][src]Crate minicbor_derive
Procedural macros to derive minicbor's Encode
and Decode
traits.
Deriving is supported for struct
s and enum
s. The encoding is optimised
for forward and backward compatibility and the overall approach is
influenced by Google's Protocol Buffers.
The goal is that ideally a change to a type still allows older software, which is unaware of the changes, to decode values of the changed type (forward compatibility) and newer software, which knows about the changes, to decode values of types which have been encoded by older software and which therefore do not include the changes made to the type (backward compatibility).
In order to reach this goal the encoding has the following characteristics:
-
The encoding does not contain any names, i.e. no field names, type names or variant names. Instead every field and every constructor needs to be annotated with an (unsigned) index number, e.g.
#[n(1)]
. -
Unknown fields are ignored during decoding.
-
Optional types default to
None
if their value is not present during decoding. -
Optional enums default to
None
if an unknown variant is encountered during decoding.
Item 1. ensures that names can be changed freely without compatibility concerns. Item 2. ensures that new fields do not affect older software. Item 3. ensures that newer software can stop producing optional values. Item 4. ensures that enums can get new variants that older software is not aware of. By "fields" we mean the elements of structs and tuple structs well as enum structs and enum tuples. In addition it is a compatible change to turn a unit variant into a struct or tuple variant if all fields are optional.
From the above it should be obvious that non-optional fields need to be present forever, so they should only be part of a type after careful consideration.
It should be emphasised that an enum
itself can not be changed in a
compatible way. An unknown variant causes an error. It is only when they
are declared as an optional field type that unknown variants of an enum
are mapped to None
. In other words, only structs can be used as
top-level types in a forward and backward compatible way, enums can not.
Example
use minicbor::{Encode, Decode}; #[derive(Encode, Decode)] struct Point { #[n(0)] x: f64, #[n(1)] y: f64 } #[derive(Encode, Decode)] struct ConvexHull { #[n(0)] left: Point, #[n(1)] right: Point, #[n(2)] points: Vec<Point>, #[n(3)] state: Option<State> } #[derive(Encode, Decode)] enum State { #[n(0)] Start, #[n(1)] Search { #[n(0)] info: u64 } }
In this example the following changes would be compatible in both directions:
-
Renaming every identifier.
-
Adding optional fields to
Point
,ConvexHull
,State::Start
orState::Search
. -
Adding more variants to
State
iffState
is only decoded as part ofConvexHull
. Direct decoding ofState
would produce anUnknownVariant
error for those new variants.
Derive Macros
Decode | Derive the |
Encode | Derive the |