From a7b2ed2b2a0287502b6a07e404c980ab3e98a527 Mon Sep 17 00:00:00 2001 From: Alex van de Sandt Date: Mon, 1 Dec 2025 22:10:20 -0600 Subject: [PATCH] Implement session string parsing with --- Cargo.lock | 72 +++++++++++++++++++++++++++++++++ Cargo.toml | 1 + examples/dump_session_string.rs | 11 +++++ src/file.rs | 17 +++++++- src/raw.rs | 8 ++++ src/telemetry.rs | 17 ++++++++ 6 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 examples/dump_session_string.rs diff --git a/Cargo.lock b/Cargo.lock index 830564c..92850cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,12 @@ dependencies = [ "libc", ] +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + [[package]] name = "autocfg" version = "1.5.0" @@ -87,6 +93,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "equator" version = "0.4.2" @@ -113,6 +128,30 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown", +] + [[package]] name = "iana-time-zone" version = "0.1.64" @@ -144,6 +183,7 @@ dependencies = [ "aligned-vec", "bytemuck", "chrono", + "saphyr", ] [[package]] @@ -183,6 +223,15 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "ordered-float" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" +dependencies = [ + "num-traits", +] + [[package]] name = "proc-macro2" version = "1.0.103" @@ -207,6 +256,29 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "saphyr" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3767dfe8889ebb55a21409df2b6f36e66abfbe1eb92d64ff76ae799d3f91016" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", + "ordered-float", + "saphyr-parser", +] + +[[package]] +name = "saphyr-parser" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb771b59f6b1985d1406325ec28f97cfb14256abcec4fdfb37b36a1766d6af7" +dependencies = [ + "arraydeque", + "hashlink", +] + [[package]] name = "shlex" version = "1.3.0" diff --git a/Cargo.toml b/Cargo.toml index 3e96907..3638048 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2024" aligned-vec = "0.6.4" bytemuck = { version = "1.24.0", features = ["derive"] } chrono = "0.4.42" +saphyr = "0.0.6" diff --git a/examples/dump_session_string.rs b/examples/dump_session_string.rs new file mode 100644 index 0000000..93de56d --- /dev/null +++ b/examples/dump_session_string.rs @@ -0,0 +1,11 @@ + +use irsdk::IbtFile; + +fn main() { + let file_name = std::env::args() + .nth(1) + .expect("Usage: dump_file "); + let file = IbtFile::from_file(&file_name).unwrap(); + + dbg!(file.session_data().unwrap()); +} diff --git a/src/file.rs b/src/file.rs index a470fde..2f08a08 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,6 +1,7 @@ use std::path::Path; use aligned_vec::{AVec, ConstAlign}; +use saphyr::LoadableYamlNode; use crate::{ raw, @@ -9,7 +10,7 @@ use crate::{ #[derive(Clone, Debug)] pub struct IbtFile { - _data: AVec>, + data: AVec>, pub header: Header, pub disk_sub_header: DiskSubHeader, @@ -28,9 +29,21 @@ impl IbtFile { let sub_header = DiskSubHeader::from_raw(&raw_sub_header); Ok(Self { - _data: data, + data, header, disk_sub_header: sub_header, }) } + + pub fn raw_session_data(&self) -> String { + let offset = self.header.session_info_offset(); + let len = self.header.session_info_len(); + let session_string = &self.data[offset..offset + len]; + String::from_utf8_lossy(session_string).into_owned() + } + + pub fn session_data(&self) -> Result { + let docs = saphyr::YamlOwned::load_from_str(&self.raw_session_data())?; + Ok(docs[0].clone()) + } } diff --git a/src/raw.rs b/src/raw.rs index 395e107..85320ea 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -77,6 +77,14 @@ impl Header { pub fn from_raw_bytes(bytes: &[u8]) -> Self { *bytemuck::from_bytes(bytes) } + + pub fn session_info_len(&self) -> i32 { + self.session_info_len + } + + pub fn session_info_offset(&self) -> i32 { + self.session_info_offset + } } impl DiskSubHeader { diff --git a/src/telemetry.rs b/src/telemetry.rs index 0302375..44ea22b 100644 --- a/src/telemetry.rs +++ b/src/telemetry.rs @@ -7,7 +7,14 @@ use crate::raw; #[derive(Clone, Copy, Debug)] pub struct Header { pub tick_rate: u32, + + /// Incremented when session info changes pub session_info_update: u32, + + /// Length in bytes of the session info string + session_info_len: usize, + /// Session info, encoded in YAML + session_info_offset: usize, } #[derive(Clone, Copy, Debug)] @@ -29,8 +36,18 @@ impl Header { Self { tick_rate: raw.tick_rate.try_into().unwrap(), session_info_update: raw.session_info_update.try_into().unwrap(), + session_info_len: raw.session_info_len().try_into().unwrap(), + session_info_offset: raw.session_info_offset().try_into().unwrap(), } } + + pub fn session_info_len(&self) -> usize { + self.session_info_len + } + + pub fn session_info_offset(&self) -> usize { + self.session_info_offset + } } impl DiskSubHeader { -- 2.51.2