aeron-glide
A safe, idiomatic Rust wrapper for the Aeron C++ API, built using cxx.
Why aeron-glide?
Previously, the Rust ecosystem relied on projects like rusteron to interface with Aeron. While rusteron successfully bridged the gap to the underlying C API, doing so heavily relied on complex generic code generation, unsafe bindings, and verbose C structs exposed directly to Rust developers. This often led to difficult-to-maintain abstractions and safety boundaries that were hard to enforce.
We decided to build something better.
aeron-glide takes a fundamentally different approach. Instead of binding strictly to the Aeron C API using bindgen, we bind directly to the Aeron C++ API using cxx. cxx creates a safe, statically verified bridge between Rust and C++, allowing us to eliminate vast amounts of boilerplate. Our C++ shim carefully wraps Aeron's Context, Publication, and Subscription objects, passing closures cleanly through trampolines into safe, idiomatic Rust structures.
The result is a fast, safe, and significantly cleaner Aeron client for Rust.
Installation
[]
= "0.1"
Prerequisites
- CMake (for building the Aeron C++ Driver from source)
- Rust 1.92+ (Cargo)
- C++14+ compiler
- Java JDK 17+ (only required when building with
--features archive)
(Note: The build.rs script will automatically fetch and compile Aeron v1.50.2 for you during the initial cargo build.)
Quick Start
use AeronClient;
let mut client = new?;
client.start;
let mut pub1 = client.add_publication?;
let mut sub1 = client.add_subscription?;
// Publish
while pub1.offer < 0
// Subscribe
sub1.poll;
Running the Examples
All examples require a running Aeron Media Driver. You can start one with:
This launches an embedded C media driver that manages shared memory buffers and handles publication/subscription matching. Keep it running in a dedicated terminal, then use any of the examples below in separate terminals.
You can optionally pass a YAML config file to tune driver settings (threading mode, buffer sizes, idle strategies, etc.):
Ping / Pong
Basic pub/sub round-trip. Sends 10 "ping!" messages and measures total time.
# Terminal 1 # Terminal 2
Exclusive publication (single-writer, lower contention):
Zero-copy publish (writes directly into Aeron's log buffer via tryClaim):
Both combined:
UDP transport (instead of IPC shared memory):
Large Ping / Pong
Sends 8 KB messages that exceed the MTU and get fragmented by Aeron. Demonstrates poll_assembled (automatic fragment reassembly) and ControlledAction (back-pressure flow control).
# Terminal 1 # Terminal 2
large_pong uses ControlledAction::Abort when it can't echo back immediately, causing Aeron to re-deliver the message on the next poll -- no user-side buffering needed.
Counters
Reads Aeron's CNC (command-and-control) counters -- real-time stats like bytes sent/received, NAKs, errors, and heartbeats.
The ping example also prints counters after its run.
Benchmarks
See BENCHMARKS.md for full results. Summary on Apple Silicon:
| Test | Result |
|---|---|
| IPC Throughput (exclusive, 32B) | ~67.5M msgs/sec |
| UDP Latency p50 (32B, localhost) | ~17.5 us |
| UDP Latency p99 (32B, localhost) | ~28.2 us |
Archive Support
The Aeron Archive enables recording streams to disk and replaying them later.
Important: The Aeron Archive server (the process that actually records and replays streams) is Java-only -- it is not exposed by the C or C++ API. You must run the Java ArchivingMediaDriver separately. This crate provides the client bindings that connect to and control that server.
Archive support is behind a Cargo feature flag because it requires Java 17+ at build time (for SBE codec generation):
If your default Java is too old, set JAVA_HOME:
JAVA_HOME=/path/to/jdk17+
Running the Archive Server
Start the Java ArchivingMediaDriver (which includes both a media driver and the archive):
This finds the aeron-all jar built during cargo build --features archive and launches the server. Keep it running in a dedicated terminal.
Record / Replay
With the archive server running:
# Terminal 2: Record 10 messages to the archive
# Terminal 3: Replay all recorded messages from the beginning
Archive Client API
The archive client API provides:
- Recording: start/stop recording any channel+stream to the archive
- Replay: replay recorded streams from any position
- Listing: query recording descriptors by ID, channel, or stream
- Position queries: get recording/start/stop/max positions
- Truncation: truncate stopped recordings
use ;
let mut archive = connect?;
// Start recording
let sub_id = archive.start_recording?;
// List recordings
archive.list_recordings?;
// Replay
let replay_session = archive.start_replay?;
Documentation
Full API documentation is available on docs.rs.
Minimum Supported Rust Version
The MSRV is 1.92.0.
License
Disclaimer: This project is not officially associated with or endorsed by Adaptive Financial Consulting Ltd. (Adaptive) or the Aeron project.
This project is dual-licensed. You may use it under either license — your choice:
- Open Source: AGPL-3.0-or-later -- free for everyone, any purpose (including commercial), provided you meet the AGPL-3.0 copyleft terms.
- Commercial: A proprietary license for those who prefer not to comply with the AGPL-3.0 copyleft obligations (e.g. building a closed-source or hosted product). See LICENSE-COMMERCIAL.md for details.
There are no restrictions based on company size or revenue: anyone may use aeron-glide for free under the AGPL-3.0.
Contributions are accepted under a lightweight Contributor License Agreement, which lets the project maintain its dual-licensing model.