Expand description
Derive macros for reliakit traits.
This crate provides #[derive(...)] support for the trait pairs defined by
other reliakit-* crates. It is written using only the standard
proc_macro API and pulls in no third-party crates. To stay free of a
full Rust-grammar parser, it reads only what the generated code needs — the
type name and its field shape — and rejects constructs it does not yet
handle with a clear compile error rather than guessing.
§Supported types
- structs with named fields
- tuple structs
- unit structs
- enums with unit, tuple, and struct variants
Unions, generic types, generic enums, enums with explicit discriminants or a
#[repr(...)], and empty enums are rejected with a compile error. The JSON
derives currently cover structs only; enums are rejected for now. The CSV
derives cover only structs with named fields, since CSV columns need names.
§reliakit-codec
CanonicalEncode and CanonicalDecode generate implementations of the
same-named traits from reliakit-codec, encoding each field in declaration
order. The derived code is exactly what a handwritten implementation would
be — one encode/decode call per field, in order.
use reliakit_codec::{decode_from_slice_exact, encode_to_vec};
use reliakit_derive::{CanonicalDecode, CanonicalEncode};
#[derive(Debug, PartialEq, CanonicalEncode, CanonicalDecode)]
struct Point {
x: u16,
y: u16,
}
let encoded = encode_to_vec(&Point { x: 10, y: 20 }).unwrap();
assert_eq!(encoded, [10, 0, 20, 0]);
assert_eq!(decode_from_slice_exact::<Point>(&encoded).unwrap(), Point { x: 10, y: 20 });Enums are supported too. Each variant is tagged by its zero-based
declaration index, encoded as a little-endian u32, followed by the
variant’s fields in declaration order:
use reliakit_codec::{decode_from_slice_exact, encode_to_vec};
use reliakit_derive::{CanonicalDecode, CanonicalEncode};
#[derive(Debug, PartialEq, CanonicalEncode, CanonicalDecode)]
enum Message {
Ping,
Pong,
}
assert_eq!(encode_to_vec(&Message::Ping).unwrap(), [0, 0, 0, 0]);
assert_eq!(encode_to_vec(&Message::Pong).unwrap(), [1, 0, 0, 0]);
assert_eq!(decode_from_slice_exact::<Message>(&[1, 0, 0, 0]).unwrap(), Message::Pong);§reliakit-json
JsonEncode and JsonDecode generate implementations of the same-named
reliakit-json traits. A struct with named fields becomes a JSON object in
declaration order, a tuple struct becomes an array, and a unit struct
becomes null. Decoding is strict; unknown object fields are ignored.
use reliakit_derive::{JsonDecode, JsonEncode};
use reliakit_json::{from_json_str, to_json_string};
#[derive(Debug, PartialEq, JsonEncode, JsonDecode)]
struct Point {
x: u16,
y: u16,
}
let json = to_json_string(&Point { x: 10, y: 20 });
assert_eq!(json, r#"{"x":10,"y":20}"#);
assert_eq!(from_json_str::<Point>(&json).unwrap(), Point { x: 10, y: 20 });§reliakit-csv
CsvEncode and CsvDecode generate implementations of the same-named
reliakit-csv traits. A struct with named fields becomes a CSV row, one
column per field in declaration order, with the field names as the header.
Because CSV columns need names, only structs with named fields are supported
— tuple structs, unit structs, and enums are rejected. Decoding is strict:
the row must have one field per struct field, and each must parse.
use reliakit_csv::{from_csv_str, to_csv_string};
use reliakit_derive::{CsvDecode, CsvEncode};
#[derive(Debug, PartialEq, CsvEncode, CsvDecode)]
struct Row {
id: u32,
name: String,
}
let rows = vec![Row { id: 1, name: "ada".into() }];
let csv = to_csv_string(&rows);
assert_eq!(csv, "id,name\r\n1,ada\r\n");
assert_eq!(from_csv_str::<Row>(&csv).unwrap(), rows);Derive Macros§
- Canonical
Decode - Derives
reliakit_codec::CanonicalDecode, decoding each field in declaration order (for enums, the variant tag first). - Canonical
Encode - Derives
reliakit_codec::CanonicalEncode, encoding each field in declaration order (for enums, the variant tag first). - CsvDecode
- Derives
reliakit_csv::CsvDecode, the inverse ofCsvEncode. Decoding is strict: the row must have exactly one field per struct field, and each field must parse into its target type. - CsvEncode
- Derives
reliakit_csv::CsvEncode: a struct with named fields becomes a row, one column per field in declaration order, with the field names as the header. - Json
Decode - Derives
reliakit_json::JsonDecode, the inverse ofJsonEncode. Decoding is strict: the JSON shape must match, and required object fields must be present; unknown object fields are ignored. - Json
Encode - Derives
reliakit_json::JsonEncode: a struct with named fields becomes a JSON object (in declaration order), a tuple struct becomes a JSON array, and a unit struct becomesnull.