| Crates.io | osal-rs-serde-derive |
| lib.rs | osal-rs-serde-derive |
| version | 0.3.2 |
| created_at | 2026-01-21 10:39:53.958788+00 |
| updated_at | 2026-01-23 16:10:26.558288+00 |
| description | Derive macros for osal-rs-serde serialization framework |
| homepage | https://github.com/HiHappyGarden/osal-rs |
| repository | https://github.com/HiHappyGarden/osal-rs |
| max_upload_size | |
| id | 2058845 |
| size | 18,046 |
Procedural macros for automatic implementation of serialization traits in osal-rs-serde.
This crate provides #[derive(Serialize, Deserialize)] macros that automatically implement the Serialize and Deserialize traits for your custom types. These macros are the recommended way to use osal-rs-serde.
Add the derive feature to enable these macros:
[dependencies]
osal-rs-serde = { version = "0.3", features = ["derive"] }
Then use the macros on your structs:
use osal_rs_serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct SensorData {
temperature: i16,
humidity: u8,
pressure: u32,
}
#[derive(Serialize, Deserialize)]
struct Point {
x: i32,
y: i32,
}
#[derive(Serialize, Deserialize)]
struct Color(u8, u8, u8);
#[derive(Serialize, Deserialize)]
struct Marker;
The derive macros work with any type that implements Serialize/Deserialize:
#[derive(Serialize, Deserialize)]
struct AllPrimitives {
a: bool,
b: u8,
c: i16,
d: u32,
e: i64,
f: f32,
g: f64,
}
#[derive(Serialize, Deserialize)]
struct WithArrays {
samples: [u16; 8],
matrix: [[f32; 3]; 3],
}
#[derive(Serialize, Deserialize)]
struct WithTuples {
coordinate: (i32, i32),
rgb: (u8, u8, u8),
}
#[derive(Serialize, Deserialize)]
struct WithOptionals {
required_id: u32,
optional_name: Option<u8>,
optional_value: Option<i16>,
}
#[derive(Serialize, Deserialize)]
struct Inner {
value: i32,
}
#[derive(Serialize, Deserialize)]
struct Outer {
id: u32,
inner: Inner,
}
alloc feature)#[derive(Serialize, Deserialize)]
struct WithCollections {
items: Vec<u32>,
name: String,
}
use osal_rs_serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct SensorReading {
sensor_id: u8,
value: i16,
timestamp: u64,
}
#[derive(Serialize, Deserialize)]
struct TelemetryPacket {
device_id: u32,
readings: [SensorReading; 4],
battery_level: u8,
status_flags: u16,
}
use osal_rs_serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MotorState {
motor_id: u8,
speed: i16,
current: u16,
enabled: bool,
}
#[derive(Serialize, Deserialize)]
struct RobotCommand {
timestamp: u64,
motors: [MotorState; 4],
emergency_stop: bool,
}
use osal_rs_serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct DeviceConfig {
device_id: u32,
baudrate: u32,
timeout_ms: Option<u16>,
retry_count: Option<u8>,
enabled: bool,
}
Fields are serialized in the order they are declared in the struct:
#[derive(Serialize, Deserialize)]
struct Example {
first: u8, // Byte 0
second: u16, // Bytes 1-2
third: u32, // Bytes 3-6
}
This produces the binary layout: [first, second_lo, second_hi, third_0, third_1, third_2, third_3]
Currently, enums are not supported by the derive macro:
// ❌ NOT SUPPORTED YET
#[derive(Serialize, Deserialize)]
enum Status {
Active,
Inactive,
}
For enums, implement the traits manually or use an integer representation:
// ✅ WORKAROUND
#[derive(Serialize, Deserialize)]
struct Status {
code: u8, // 0 = Inactive, 1 = Active
}
Unions are not supported:
// ❌ NOT SUPPORTED
#[derive(Serialize, Deserialize)]
union Data {
integer: i32,
float: f32,
}
Generic types are not yet supported in the current version:
// ❌ NOT SUPPORTED YET
#[derive(Serialize, Deserialize)]
struct Container<T> {
value: T,
}
The derive macros generate implementations similar to:
// For this struct:
#[derive(Serialize, Deserialize)]
struct Point {
x: i32,
y: i32,
}
// The macro generates approximately:
impl Serialize for Point {
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.serialize_struct_start("Point", 2)?;
serializer.serialize_field("x", &self.x)?;
serializer.serialize_field("y", &self.y)?;
serializer.serialize_struct_end()?;
Ok(())
}
}
impl Deserialize for Point {
fn deserialize<D: Deserializer>(deserializer: &mut D, name: &str) -> Result<Self, D::Error> {
deserializer.deserialize_struct_start(name)?;
let result = Self {
x: deserializer.deserialize_field::<i32>("x")?,
y: deserializer.deserialize_field::<i32>("y")?,
};
deserializer.deserialize_struct_end()?;
Ok(result)
}
}
To see the generated code, use cargo expand:
cargo install cargo-expand
cargo expand --example your_example
Common errors and solutions:
T: Serialize is not satisfied"Solution: Ensure all field types implement Serialize:
#[derive(Serialize, Deserialize)]
struct MyType {
value: CustomType, // CustomType must implement Serialize
}
Solution: Make sure you're using a supported struct type (named fields, tuple, or unit).
The derive macros generate efficient code with:
alloc feature)See the parent crate's examples/ directory for complete working examples:
with_derive.rs - Basic usagearrays_tuples.rs - Arrays and tuplesnested_structs.rs - Nested structuresoptional_fields.rs - Optional fieldsrobot_control.rs - Complex embedded exampleGPL-3.0 - See LICENSE for details.
Antonio Salsi passy.linux@zresa.it