| Crates.io | pitwall |
| lib.rs | pitwall |
| version | 0.1.0 |
| created_at | 2025-10-31 21:43:47.368383+00 |
| updated_at | 2025-10-31 21:43:47.368383+00 |
| description | Modern, type-safe Rust library for iRacing telemetry data |
| homepage | https://werace.au/opensource/pitwall |
| repository | |
| max_upload_size | |
| id | 1910863 |
| size | 427,071 |
Core Rust crate for the Pitwall telemetry stack. It provides the public API for:
Pitwall::connect)..ibt files on any platform (Pitwall::open).PitwallFrame adapters.If you are looking for the full project overview (architecture, roadmap, contributing), read the repository-level README.md. This file focuses solely on using the published crate.
[dependencies]
pitwall = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
futures = "0.3"
| Feature | Default | Description |
|---|---|---|
derive |
✅ | Pulls in pitwall-derive so you can #[derive(PitwallFrame)]. Disable if you implement adapters manually. |
tauri |
❌ | Re-exports helpers needed by pitwall-tauri (Specta integration). |
schema-discovery |
❌ | Enables experimental schema introspection utilities. |
benchmark |
❌ | Builds micro-benchmarks found under benches/. |
Enable additional flags in your manifest, e.g.:
pitwall = { version = "0.1", features = ["tauri", "schema-discovery"] }
use pitwall::{Pitwall, PitwallFrame, UpdateRate};
use futures::StreamExt;
#[derive(Debug, PitwallFrame)]
struct CarData {
#[field_name = "Speed"]
speed: f32,
#[field_name = "Gear"]
gear: Option<i32>,
}
#[tokio::main]
async fn main() -> pitwall::Result<()> {
let connection = Pitwall::connect().await?;
let mut stream = connection.subscribe::<CarData>(UpdateRate::Native);
while let Some(frame) = stream.next().await {
println!("Speed: {speed:.1}, Gear: {:?}", frame.gear);
}
Ok(())
}
use pitwall::{Pitwall, PitwallFrame, UpdateRate};
use futures::StreamExt;
#[derive(Debug, PitwallFrame)]
struct CarData {
#[field_name = "Speed"]
speed: f32,
#[field_name = "RPM"]
rpm: f32,
}
#[tokio::main]
async fn main() -> pitwall::Result<()> {
let connection = Pitwall::open("./test-data/race.ibt").await?;
let mut stream = connection.subscribe::<CarData>(UpdateRate::Max(30));
while let Some(frame) = stream.next().await {
println!("Speed: {speed:.1} RPM: {rpm}");
}
Ok(())
}
Both connection types expose the same API surface—switching between live and replay sources is just a constructor change.
The PitwallFrame derive macro (enabled by the default derive feature) generates a zero-copy adapter for your struct. Key attributes:
#[field_name = "Speed"] – map a struct field to an iRacing telemetry variable.Option<T> – optional telemetry; None if the source is missing.#[missing = "value"] – provide a literal or expression fallback when the telemetry channel is absent.#[fail_if_missing] – aborts connection validation if the channel does not exist.#[calculated = "expr"] – compute a value at runtime without reading telemetry.#[skip] – field managed entirely by your application (not populated by Pitwall).See the pitwall-derive crate for the full attribute matrix and pitwall/tests/typescript_generation.rs for an end-to-end example.
let conn = Pitwall::connect().await?;
let mut telemetry = conn.subscribe::<CarData>(UpdateRate::Native);
let mut session = conn.session_updates();
while let Some(info) = session.next().await {
println!("Track: {}", info.weekend_info.track_display_name);
}
You may spawn multiple subscribers simultaneously; internally Pitwall fans out the producer data using Tokio watch channels, keeping frame construction under 1 ms even with hundreds of subscribers.
cfg(windows) gates for memory-mapped IPC.pitwall-derive: standalone copy of the derive macro (already included when you keep the default derive feature enabled).pitwall-tauri: helpers for streaming telemetry into Tauri + Specta type generation pipelines.MIT License. See LICENSE in this crate for details.