Expand description
§Byteable
A Rust crate for convenient serialization and deserialization of byte-oriented data.
byteable provides traits and utilities for seamless conversion between data structures
and byte arrays, handling both synchronous and asynchronous I/O operations, and managing
endianness.
§Features
ByteableTrait: The core trait for types that can be converted to and from a byte array.ReadByteable&WriteByteableTraits: Extension traits forstd::io::Readandstd::io::Write, enabling convenient reading and writing ofByteabletypes.AsyncReadByteable&AsyncWriteByteableTraits (withtokiofeature): Asynchronous counterparts toReadByteableandWriteByteable, designed for use withtokio’s async I/O.EndianConvertTrait & Wrappers: Provides methods for converting primitive types between different endianness (little-endian and big-endian), along withBigEndian<T>andLittleEndian<T>wrapper types.#[derive(Byteable)](withderivefeature): A procedural macro that automatically implements theByteabletrait for structs, significantly simplifying boilerplate. For advanced use cases,#[derive(UnsafeByteableTransmute)]is also available for manual transmute-based implementations.
§Quick Start
Add byteable to your Cargo.toml:
[dependencies]
byteable = { version = "*", features = ["derive"] }§Basic Usage
The core workflow involves:
- Defining a struct with explicit memory layout (
#[repr(C, packed)]) - Deriving or implementing the
Byteabletrait - Using extension traits for reading/writing
§Example: File I/O
use byteable::{Byteable, ReadByteable, WriteByteable};
use std::fs::File;
#[derive(Byteable, Debug, PartialEq, Clone, Copy)]
struct Packet {
id: u8,
#[byteable(little_endian)]
length: u16,
data: [u8; 4],
}
// Create a packet
let packet = Packet {
id: 42,
length: 1024,
data: [0xDE, 0xAD, 0xBE, 0xEF],
};
// Write to file
let mut file = File::create("packet.bin")?;
file.write_byteable(packet)?;
// Read from file
let mut file = File::open("packet.bin")?;
let restored: Packet = file.read_byteable()?;
assert_eq!(packet, restored);§Example: Network Protocol
use byteable::Byteable;
#[derive(Byteable, Debug, Clone, Copy)]
struct NetworkHeader {
#[byteable(big_endian)]
magic: u32, // Network byte order (big-endian)
version: u8,
flags: u8,
#[byteable(little_endian)]
payload_len: u16, // Little-endian for payload
}§Example: Working with TCP Streams
use byteable::{Byteable, ReadByteable, WriteByteable};
use std::net::TcpStream;
#[derive(Byteable, Debug, Clone, Copy)]
struct Message {
msg_type: u8,
data: [u8; 16],
}
let mut stream = TcpStream::connect("127.0.0.1:8080")?;
// Write message
let msg = Message {
msg_type: 1,
data: [0; 16],
};
stream.write_byteable(msg)?;
// Read response
let response: Message = stream.read_byteable()?;§Async I/O (with tokio feature)
Enable async support in your Cargo.toml:
[dependencies]
byteable = { version = "*", features = ["derive", "tokio"] }
tokio = { version = "1", features = ["full"] }Example usage:
{
use byteable::{AsyncReadByteable, AsyncWriteByteable, Byteable};
use tokio::net::TcpStream;
#[derive(Byteable, Debug, Clone, Copy)]
struct AsyncPacket {
#[byteable(little_endian)]
id: u32,
data: [u8; 8],
}
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
let packet = AsyncPacket {
id: 123,
data: [1, 2, 3, 4, 5, 6, 7, 8],
};
stream.write_byteable(packet).await?;
let response: AsyncPacket = stream.read_byteable().await?;§Endianness Handling
The crate provides BigEndian<T> and LittleEndian<T> wrappers for handling byte order:
use byteable::{BigEndian, LittleEndian};
// Create endian-aware values
let big = BigEndian::new(0x12345678u32);
let little = LittleEndian::new(0x12345678u32);
// Get raw bytes (in specified endianness)
assert_eq!(big.raw_bytes(), [0x12, 0x34, 0x56, 0x78]);
assert_eq!(little.raw_bytes(), [0x78, 0x56, 0x34, 0x12]);
// Convert back to native value
assert_eq!(big.get(), 0x12345678u32);
assert_eq!(little.get(), 0x12345678u32);§Safety Considerations
The #[derive(Byteable)] macro uses core::mem::transmute internally, which is unsafe.
When using this macro, ensure that:
- All fields are primitive types or have endianness attributes (
#[byteable(big_endian)],#[byteable(little_endian)]) - The struct doesn’t contain types with invalid bit patterns (e.g.,
bool,char, enums)
For types with complex invariants (like String, Vec, references, etc.), do not use
the Byteable derive macro. Use only with plain old data (POD) types.
§Advanced Usage
§Custom Byteable Implementation
The #[derive(Byteable)] macro handles most use cases automatically, including
endianness conversion via attributes:
#![cfg(feature = "derive")]
use byteable::Byteable;
#[derive(Byteable, Debug, PartialEq, Clone, Copy)]
struct Point {
#[byteable(little_endian)]
x: i32,
#[byteable(little_endian)]
y: i32,
}
let point = Point { x: 10, y: 20 };
let bytes = point.to_byte_array();
let restored = Point::from_byte_array(bytes);
assert_eq!(point, restored);For advanced cases, you can still use the impl_byteable_via! macro with manual
implementations. See the trait documentation for details.
§Feature Flags
derive: Enables the#[derive(Byteable)]procedural macro (default: enabled)tokio: Enables async I/O traits for use with tokio (default: disabled)
§Performance
This crate is designed for zero-copy, zero-overhead serialization. Operations like
to_byte_array and from_byte_array typically compile down to simple memory operations
or even no-ops when possible.
Macros§
- impl_
byteable_ via - Implements
Byteablefor a type by delegating to another type. - unsafe_
byteable_ transmute - Implements
Byteablefor one or more types usingtransmute.
Structs§
- BigEndian
- A wrapper type that stores a value in big-endian (network) byte order.
- Little
Endian - A wrapper type that stores a value in little-endian byte order.
Traits§
- Byte
Array - A trait for types that can be used as byte array representations.
- Byteable
- A trait for types that can be converted to and from a byte array.
- Byteable
Raw - A trait for types that have a corresponding raw representation type.
- Endian
Convert - A trait for types that can be converted between different byte orders (endianness).
- Read
Byteable - Extension trait for
Readthat adds methods for readingByteabletypes. - Valid
Bytecast Marker - Marker trait for types that are safe to transmute to and from byte arrays.
- Write
Byteable - Extension trait for
Writethat adds methods for writingByteabletypes.
Derive Macros§
- Byteable
- Derives a delegate pattern for
Byteableby generating a raw struct with endianness markers. - Unsafe
Byteable Transmute - Derives the
Byteabletrait for a struct usingtransmute.