Skip to main content

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:
TypeSize (bytes)
bool1
u8, i81
u16, i162
u32, i32, f324
u64, i64, f648
[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