Rust Byte Record

access data bytes

Concept:

Utilities for serializing primitive values to byte arrays and deserializing them back, written in Rust. The crate provides a small, dependency-free toolkit for laying primitives and strings into byte buffers and reading them back out - useful for fixed-format records, message framing, and inter-process communication where a fixed-layout byte representation is needed.

Components:

The crate exposes three independent abstractions that share the same serialization helpers.
ComponentKindBacking storageRole
ByteRecord type alias stack array [u8; 32] Fixed-size record manipulated through free functions
ByteArray struct Box<[u8; 32]> Same fixed size, boxed on the heap, with methods
Message struct Vec<u8> Variable-size message with a type tag and content-size header
All three share a common set of primitive-conversion helpers (usize, i32, &str) so the same encoding rules apply regardless of which container holds the bytes.

Constants:

ConstantValueMeaning
BYTE_RECORD_SIZE 32 Fixed length of ByteRecord and ByteArray
TYPE_SIZE 1 Message header byte that carries the MsgType tag
CONTENT_SIZE 8 Message header field that stores the content length as a big-endian usize
MSG_SIZE 4096 Suggested maximum total Message size
A Message payload therefore starts at offset TYPE_SIZE + CONTENT_SIZE = 9, leaving up to MSG_SIZE - 9 = 4087 bytes of content when the suggested cap is honored.

Quick Start:

# Build the library
cargo build

# Run the bundled example
cargo run --example test1

# Run the unit tests
cargo test
Use it from another crate by adding a path dependency in Cargo.toml:
[dependencies]
rust_byte_record = { path = "../RustByteRecord" }
use rust_byte_record::*;

fn main() {
    let mut br: ByteRecord = [0; BYTE_RECORD_SIZE];
    set_field(&mut br, 2, &usize_to_bytes(255));
    show_record(&br, 8);
}

Free Functions:

Endianness is big-endian for every numeric conversion, so byte buffers can be moved between processes and architectures without reinterpretation.
FunctionSignaturePurpose
usize_to_bytes fn(usize) -> [u8; 8] usize to 8-byte big-endian array
usize_from_bytes fn(&[u8]) -> usize 8-byte slice back to usize
i32_to_bytes fn(i32) -> [u8; 4] i32 to 4-byte big-endian array
i32_from_bytes fn(&[u8]) -> i32 4-byte slice back to i32
str_to_bytes fn(&str) -> &[u8] Borrow the UTF-8 bytes of a &str
str_from_bytes fn(&[u8]) -> Result<&str, Utf8Error> Decode a slice as UTF-8
clear fn(&mut ByteRecord) Zero every byte of a ByteRecord
set_field fn(&mut ByteRecord, offset: usize, buff: &[u8]) Copy buff into the record at offset, bounds-checked
show_record fn(&ByteRecord, fold: usize) Print a folded, decimal dump of the record
usize_from_bytes and i32_from_bytes expect slices of exactly the matching length (8 and 4 bytes respectively) - they panic via unwrap() on a length mismatch.

ByteRecord:

pub const BYTE_RECORD_SIZE: usize = 32;
pub type ByteRecord = [u8; BYTE_RECORD_SIZE];
A type alias for a 32-byte stack array. Manipulated through the free functions above, so no allocation occurs.
let mut br: ByteRecord = [0; BYTE_RECORD_SIZE];
let buff: [u8; 4] = [1, 2, 3, 4];
set_field(&mut br, 3, &buff);
show_record(&br, 8);

ByteArray:

A heap-resident counterpart to ByteRecord - a Box<[u8; 32]> wrapped in a struct that exposes equivalent operations as methods.
MethodPurpose
new()Allocate a zeroed boxed array
len() / is_empty()Length helpers
array()Borrow the underlying &[u8; 32]
clear()Zero every byte
set_field(offset, buff)Copy buff into the array, bounds-checked
get_field(offset, size)Borrow a sub-slice
set_str(offset, s)Write the UTF-8 bytes of s
get_str(offset, size)Decode a sub-slice as UTF-8
show_record(fold)Folded decimal dump
let mut ba = ByteArray::new();
ba.set_str(4, "a literal string");
let s = ba.get_str(4, "a literal string".len()).unwrap();

Message:

A variable-length, framed buffer suitable for byte-oriented messaging. The backing storage is a Vec<u8> whose layout is:
+--------+----------------------+--------------------------+
| type   | content size         | content                  |
| 1 byte | 8 bytes (BE usize)   | content_size bytes       |
+--------+----------------------+--------------------------+
The first byte is an MsgType tag, the next eight bytes encode the content length as a big-endian usize, and the remainder is the payload.

MsgType

pub enum MsgType {
    DEFAULT = 0,
    TEXT    = 1,
    REPLY   = 2,
    END     = 4,
    QUIT    = 8,
}
The discriminants are powers of two so callers may treat them as bit flags when that is useful.

Primary interface

MethodPurpose
new(sz)Allocate a message buffer of sz bytes, zero-initialized
init()Re-zero an existing message in place, preserving its length
len() / is_empty()Length helpers
set_type(t) / get_type()Read or write the type tag
set_content_bytes(buff)Write the payload bytes and update the content-size header
get_content_bytes()Borrow the current payload as &[u8]
set_content_str(s)Write a &str payload (UTF-8) and update the size header
get_content_str()Decode the payload as UTF-8
show_message(fold)Folded decimal dump of the entire buffer

Secondary interface

Lower-level access for callers who want to build their own framing on top of the buffer.
MethodPurpose
set_field(offset, buff) / get_field(offset, size)Raw byte read/write
set_content_size(sz) / get_content_size()Read or write just the size header
set_str(offset, s) / get_str(offset, size)Raw UTF-8 read/write
array()Borrow the entire backing buffer as &[u8]
let mut msg = Message::new(32);
msg.set_type(MsgType::TEXT);
msg.set_content_str("a literal string");
let s = msg.get_content_str().unwrap();

Examples:

A worked example that exercises every type lives in examples/test1.rs:
cargo run --example test1
It walks through:
  • Round-tripping usize, i32, and &str through their byte representations
  • Filling a ByteRecord with a buffer at an offset
  • Storing and retrieving structured data inside a ByteArray
  • Building a Message, setting its type, and reading its payload back

Build and Test:

# Build
cargo build

# Run the bundled example
cargo run --example test1

# Unit tests
cargo test
This crate uses only the Rust standard library - no external dependencies.

Status:

Active work in progress. The primary types and conversion helpers are stable and exercised by the example. Future work may add typed accessors for additional primitive widths (u8, u16, u64, f32, f64), iterator adaptors over Message payloads, and richer error reporting in place of the current unwrap() paths in the fixed-width conversion helpers.