Skip to main content

Crate reliakit_derive

Crate reliakit_derive 

Source
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§

CanonicalDecode
Derives reliakit_codec::CanonicalDecode, decoding each field in declaration order (for enums, the variant tag first).
CanonicalEncode
Derives reliakit_codec::CanonicalEncode, encoding each field in declaration order (for enums, the variant tag first).
CsvDecode
Derives reliakit_csv::CsvDecode, the inverse of CsvEncode. 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.
JsonDecode
Derives reliakit_json::JsonDecode, the inverse of JsonEncode. Decoding is strict: the JSON shape must match, and required object fields must be present; unknown object fields are ignored.
JsonEncode
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 becomes null.