Overview
Cerulion Core supports serialization for various types when using Copy types with #[repr(C)]. This page documents all supported types and their usage.
Primitive Types
All primitive types are supported:
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct Primitives {
flag: bool,
byte: u8,
short: u16,
int: u32,
long: u64,
signed_byte: i8,
signed_short: i16,
signed_int: i32,
signed_long: i64,
real: f32,
double_real: f64,
}
Fixed-Size Arrays
Fixed-size arrays of primitives work automatically:
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct ArrayData {
values: [f32; 10],
flags: [bool; 8],
}
Fixed-Size Strings
Use fixed-size byte arrays for strings (not String):
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct UserData {
id: u32,
username: [u8; 32], // Fixed 32 bytes (not String!)
email: [u8; 64], // Fixed 64 bytes
}
Don’t use String or Vec in your message types. These are heap-allocated and don’t implement Copy. Use fixed-size byte arrays ([u8; N]) instead.
Nested Structs
Nested Copy structs work as long as the outer struct is #[repr(C)]:
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct Position3D {
x: f32,
y: f32,
z: f32,
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct RobotState {
position: Position3D,
orientation: Position3D,
timestamp: u64,
}
Safety Considerations
Safe Types
Raw byte serialization using #[repr(C)] is safe for:
- ✅ Primitive types (
u8, u16, u32, u64, i8, i16, i32, i64, f32, f64, bool)
- ✅ Arrays of primitive types (
[f32; 10])
- ✅ Structs containing only primitives (with
#[repr(C)])
- ✅ Fixed-size byte arrays (
[u8; N])
- ✅ Nested
Copy structs (with #[repr(C)])
Unsafe Types
Avoid using raw serialization for:
- ❌ Types with pointers or references
- ❌ Types with padding-dependent layouts (use
#[repr(C)] to fix)
- ❌
String (use [u8; N] instead)
- ❌
Vec, HashMap, or other heap-allocated collections
- ❌ Types with
Drop implementations that manage resources
- ❌ Types that don’t implement
Copy
Using unsafe types can lead to memory corruption, data loss, or undefined behavior. Always use Copy types with #[repr(C)] for message types.
Type Size Reference
Common type sizes for reference:
| Type | Size (bytes) |
|---|
bool | 1 |
u8, i8 | 1 |
u16, i16 | 2 |
u32, i32, f32 | 4 |
u64, i64, f64 | 8 |
[T; N] | N * size_of::<T>() |
Examples
Example 1: Simple Sensor Data
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct SensorData {
temperature: f32,
pressure: f32,
timestamp: u64,
}
Example 2: Fixed-Size Arrays
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct JointState {
positions: [f32; 20],
velocities: [f32; 20],
timestamp: u64,
}
Example 3: Fixed-Size Strings
#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct UserData {
id: u32,
username: [u8; 32],
email: [u8; 64],
}
Next Steps