Expand description
Derive macros for OxiCode
This crate provides derive macros for the Encode and Decode traits in the
OxiCode binary serialization library.
§Usage
Add oxicode to your Cargo.toml with the derive feature enabled:
[dependencies]
oxicode = { version = "0.1", features = ["derive"] }Then derive Encode, Decode, and BorrowDecode on your types:
use oxicode::{Encode, Decode};
#[derive(Encode, Decode)]
struct Point {
x: f32,
y: f32,
}
#[derive(Encode, Decode)]
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
}§Field Attributes
The derive macros support field-level attributes via #[oxicode(...)]:
§#[oxicode(skip)]
Skip the field during encoding. During decoding, the field’s value will be
set to Default::default(). This is useful for fields that should not be
serialized (e.g., computed caches, internal state, or transient fields).
use oxicode::{Encode, Decode};
#[derive(Encode, Decode)]
struct Config {
id: u32,
name: String,
#[oxicode(skip)]
cached_hash: u64, // not encoded; restored as 0 on decode
}§#[oxicode(default = "fn_path")]
Use a custom default function instead of Decode::decode when decoding.
The function is called with no arguments and must return the field type.
This is useful for providing a non-Default fallback value.
use oxicode::{Encode, Decode};
fn default_limit() -> u32 { 100 }
#[derive(Encode, Decode)]
struct Settings {
name: String,
#[oxicode(default = "default_limit")]
limit: u32, // decoded normally, but if needed default_limit() is the fallback
}Note: default = "fn_path" implies skipping the field during both encode and
decode (the field is excluded from the binary stream and the default function
is called to produce the value). To encode normally while specifying a default
factory, combine with struct-level versioning.
§#[oxicode(flatten)]
Inline the fields of the nested struct directly into the encoding stream.
In OxiCode’s binary format, structs are already encoded as a plain sequential
byte stream with no struct headers or length prefixes, so flatten is a
semantic no-op — the binary output is identical to normal encoding.
This attribute exists primarily for compatibility with code migrating from
serde where #[serde(flatten)] is commonly used. The nested type must
implement Encode + Decode.
use oxicode::{Encode, Decode};
#[derive(Encode, Decode)]
struct Address { city: String, zip: u32 }
#[derive(Encode, Decode)]
struct Person {
name: String,
#[oxicode(flatten)]
address: Address, // city and zip encoded in-sequence, no wrapper
}§Container Attributes
§#[oxicode(bound = "T: SomeTrait")]
Override the auto-generated where clause for all three trait impls (Encode, Decode,
BorrowDecode). When present, the auto-generated bounds are replaced by the predicates
in the string. An empty string "" means no bounds are added.
§#[oxicode(rename_all = "camelCase")]
Accepted without error for serde migration compatibility. In OxiCode’s binary format this is a no-op on the wire (fields are positional).
§#[oxicode(crate = "my_oxicode")]
Override the path used to reference OxiCode items in generated code. Default is ::oxicode.
§Supported Types
The derive macros support:
- Structs with named fields
- Structs with unnamed fields (tuple structs)
- Unit structs
- Enums with any combination of named, unnamed, and unit variants
- Full generic type parameter support
- Lifetime parameter support
- Where clauses and bounds
§Generics
The derive macros automatically add appropriate trait bounds to generic type parameters:
use oxicode::{Encode, Decode};
#[derive(Encode, Decode)]
struct Container<T> {
value: T,
}
// This generates:
// impl<T: Encode> Encode for Container<T> { ... }
// impl<T: Decode> Decode for Container<T> { ... }§Limitations
- Unions are not supported due to safety concerns
- For complex scenarios requiring custom serialization logic, implement the traits manually
Derive Macros§
- Borrow
Decode - Derive macro for the
BorrowDecodetrait - Decode
- Derive macro for the
Decodetrait - Encode
- Derive macro for the
Encodetrait