Skip to content

Commit 3cced9a

Browse files
authored
Resolve #11: Eliminate code duplication in BBL parser (#12)
* refactor: move sign_extend helpers to crate library (Phase 1) - Create src/parser/helpers.rs with 7 sign_extend functions - Export helpers from parser/mod.rs - Remove bbl_format from lib.rs (will be CLI-only module) - Update stream.rs to use shared helpers - Update bbl_format.rs to use shared helpers - All tests pass, CSV output identical to master * refactor: unify parse_frame_data and BBLDataStream (Phase 2+3) - Add debug parameter to crate's parse_frame_data - Add apply_predictor_with_debug with field_names, skipped_frames support - Add vbatLatest corruption prevention logic to crate - Add read_tag8_8svb_counted method with proper group counting - Fix ENCODING_TAG8_8SVB handling to count consecutive fields - Update main.rs to import from bbl_parser crate: * BBLDataStream, parse_frame_data, FrameDefinition * sign_extend_14bit, encoding constants - Remove duplicate FieldDefinition/FrameDefinition from main.rs - Delete bbl_format.rs entirely (509 lines removed) - All CSV outputs verified identical to master branch * fix: simplify PREDICT_MINMOTOR logic (remove dead code) Remove nonsensical string parsing of i32 values in PREDICT_MINMOTOR. Since sysconfig is HashMap<String, i32>, the values are already integers and don't need comma-separated string parsing. Addresses CodeRabbit review feedback. * refactor: address CodeRabbit nitpick feedback - Extract magic number 1000 to MAX_REASONABLE_VBAT_RAW constant - Add debug logging for PREDICT_MOTOR_0 hardcoded fallback - Remove redundant function-scoped import (decoder::* glob already includes it) All tests pass, no clippy warnings. * refactor: reorganize MAX_REASONABLE_VBAT_RAW constant placement Move MAX_REASONABLE_VBAT_RAW constant to after predictor constants for better organization. Groups domain-specific constants together and improves code clarity by placing the constant near related corruption detection logic.
1 parent e20e467 commit 3cced9a

9 files changed

Lines changed: 409 additions & 879 deletions

File tree

src/bbl_format.rs

Lines changed: 0 additions & 655 deletions
This file was deleted.

src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
//! ```
1717
1818
// Module declarations
19-
mod bbl_format;
2019
pub mod conversion;
2120
pub mod error;
2221
pub mod export;
@@ -25,8 +24,6 @@ pub mod types;
2524

2625
// Re-export everything from modules for convenience
2726
#[allow(ambiguous_glob_reexports)]
28-
pub use bbl_format::*;
29-
#[allow(ambiguous_glob_reexports)]
3027
pub use conversion::*;
3128
#[allow(ambiguous_glob_reexports)]
3229
pub use error::*;

src/main.rs

Lines changed: 34 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
mod bbl_format;
2-
31
use anyhow::{Context, Result};
42
use clap::{Arg, Command};
53
use glob::glob;
@@ -15,6 +13,16 @@ use bbl_parser::conversion::{
1513
format_failsafe_phase, format_flight_mode_flags, format_state_flags,
1614
};
1715

16+
// Import parser types from crate library
17+
use bbl_parser::parser::helpers::sign_extend_14bit;
18+
use bbl_parser::parser::{
19+
parse_frame_data, BBLDataStream, ENCODING_NEG_14BIT, ENCODING_NULL, ENCODING_SIGNED_VB,
20+
ENCODING_TAG2_3S32, ENCODING_UNSIGNED_VB,
21+
};
22+
23+
// Import types from crate library
24+
use bbl_parser::types::FrameDefinition;
25+
1826
/// Maximum recursion depth to prevent stack overflow
1927
const MAX_RECURSION_DEPTH: usize = 100;
2028

@@ -224,72 +232,7 @@ fn find_bbl_files_in_dir_with_depth(
224232
Ok(bbl_files)
225233
}
226234

227-
#[derive(Debug, Clone)]
228-
struct FieldDefinition {
229-
name: String,
230-
signed: bool,
231-
predictor: u8,
232-
encoding: u8,
233-
}
234-
235-
#[derive(Debug, Clone)]
236-
struct FrameDefinition {
237-
fields: Vec<FieldDefinition>,
238-
field_names: Vec<String>,
239-
count: usize,
240-
}
241-
242-
impl FrameDefinition {
243-
fn new() -> Self {
244-
Self {
245-
fields: Vec::new(),
246-
field_names: Vec::new(),
247-
count: 0,
248-
}
249-
}
250-
251-
fn from_field_names(names: Vec<String>) -> Self {
252-
let fields = names
253-
.iter()
254-
.map(|name| FieldDefinition {
255-
name: name.clone(),
256-
signed: false,
257-
predictor: 0,
258-
encoding: 0,
259-
})
260-
.collect();
261-
let count = names.len();
262-
Self {
263-
fields,
264-
field_names: names,
265-
count,
266-
}
267-
}
268-
269-
fn update_signed(&mut self, signed_data: &[bool]) {
270-
for (i, field) in self.fields.iter_mut().enumerate() {
271-
if i < signed_data.len() {
272-
field.signed = signed_data[i];
273-
}
274-
}
275-
}
276-
277-
fn update_predictors(&mut self, predictors: &[u8]) {
278-
for (i, field) in self.fields.iter_mut().enumerate() {
279-
if i < predictors.len() {
280-
field.predictor = predictors[i];
281-
}
282-
}
283-
}
284-
285-
fn update_encoding(&mut self, encodings: &[u8]) {
286-
for (i, field) in self.fields.iter_mut().enumerate() {
287-
if i < encodings.len() {
288-
field.encoding = encodings[i];
289-
}
290-
}
291-
}
292-
}
235+
// FieldDefinition and FrameDefinition now imported from bbl_parser::types
293236

294237
#[derive(Debug)]
295238
struct BBLHeader {
@@ -1763,7 +1706,7 @@ fn parse_frames(
17631706
// GPS frame history for differential encoding
17641707
let mut gps_frame_history: Vec<i32> = Vec::new();
17651708

1766-
let mut stream = bbl_format::BBLDataStream::new(binary_data);
1709+
let mut stream = BBLDataStream::new(binary_data);
17671710

17681711
// Main frame parsing loop - process frames as a stream, don't store all
17691712
while !stream.eof {
@@ -1804,7 +1747,7 @@ fn parse_frames(
18041747
// I-frames reset the prediction history
18051748
frame_history.current_frame.fill(0);
18061749

1807-
if bbl_format::parse_frame_data(
1750+
if parse_frame_data(
18081751
&mut stream,
18091752
&header.i_frame_def,
18101753
&mut frame_history.current_frame,
@@ -1886,7 +1829,7 @@ fn parse_frames(
18861829
if header.p_frame_def.count > 0 && frame_history.valid {
18871830
let mut p_frame_values = vec![0i32; header.p_frame_def.count];
18881831

1889-
if bbl_format::parse_frame_data(
1832+
if parse_frame_data(
18901833
&mut stream,
18911834
&header.p_frame_def,
18921835
&mut p_frame_values,
@@ -2080,7 +2023,7 @@ fn parse_frames(
20802023

20812024
let mut g_frame_values = vec![0i32; header.g_frame_def.count];
20822025

2083-
if bbl_format::parse_frame_data(
2026+
if parse_frame_data(
20842027
&mut stream,
20852028
&header.g_frame_def,
20862029
&mut g_frame_values,
@@ -2354,7 +2297,7 @@ fn parse_frames(
23542297

23552298
#[allow(dead_code)]
23562299
fn parse_i_frame(
2357-
stream: &mut bbl_format::BBLDataStream,
2300+
stream: &mut BBLDataStream,
23582301
frame_def: &FrameDefinition,
23592302
debug: bool,
23602303
) -> Result<HashMap<String, i32>> {
@@ -2363,12 +2306,10 @@ fn parse_i_frame(
23632306
// Parse each field according to the frame definition
23642307
for field in &frame_def.fields {
23652308
let value = match field.encoding {
2366-
bbl_format::ENCODING_SIGNED_VB => stream.read_signed_vb()?,
2367-
bbl_format::ENCODING_UNSIGNED_VB => stream.read_unsigned_vb()? as i32,
2368-
bbl_format::ENCODING_NEG_14BIT => {
2369-
-(bbl_format::sign_extend_14bit(stream.read_unsigned_vb()? as u16))
2370-
}
2371-
bbl_format::ENCODING_NULL => 0,
2309+
ENCODING_SIGNED_VB => stream.read_signed_vb()?,
2310+
ENCODING_UNSIGNED_VB => stream.read_unsigned_vb()? as i32,
2311+
ENCODING_NEG_14BIT => -(sign_extend_14bit(stream.read_unsigned_vb()? as u16)),
2312+
ENCODING_NULL => 0,
23722313
_ => {
23732314
if debug {
23742315
println!(
@@ -2387,7 +2328,7 @@ fn parse_i_frame(
23872328
}
23882329

23892330
fn parse_s_frame(
2390-
stream: &mut bbl_format::BBLDataStream,
2331+
stream: &mut BBLDataStream,
23912332
frame_def: &FrameDefinition,
23922333
debug: bool,
23932334
) -> Result<HashMap<String, i32>> {
@@ -2398,22 +2339,22 @@ fn parse_s_frame(
23982339
let field = &frame_def.fields[field_index];
23992340

24002341
match field.encoding {
2401-
bbl_format::ENCODING_SIGNED_VB => {
2342+
ENCODING_SIGNED_VB => {
24022343
let value = stream.read_signed_vb()?;
24032344
data.insert(field.name.clone(), value);
24042345
field_index += 1;
24052346
}
2406-
bbl_format::ENCODING_UNSIGNED_VB => {
2347+
ENCODING_UNSIGNED_VB => {
24072348
let value = stream.read_unsigned_vb()? as i32;
24082349
data.insert(field.name.clone(), value);
24092350
field_index += 1;
24102351
}
2411-
bbl_format::ENCODING_NEG_14BIT => {
2412-
let value = -(bbl_format::sign_extend_14bit(stream.read_unsigned_vb()? as u16));
2352+
ENCODING_NEG_14BIT => {
2353+
let value = -(sign_extend_14bit(stream.read_unsigned_vb()? as u16));
24132354
data.insert(field.name.clone(), value);
24142355
field_index += 1;
24152356
}
2416-
bbl_format::ENCODING_TAG2_3S32 => {
2357+
ENCODING_TAG2_3S32 => {
24172358
// This encoding handles 3 fields at once
24182359
let mut values = [0i32; 8];
24192360
stream.read_tag2_3s32(&mut values)?;
@@ -2427,7 +2368,7 @@ fn parse_s_frame(
24272368
}
24282369
field_index += 3;
24292370
}
2430-
bbl_format::ENCODING_NULL => {
2371+
ENCODING_NULL => {
24312372
data.insert(field.name.clone(), 0);
24322373
field_index += 1;
24332374
}
@@ -2450,7 +2391,7 @@ fn parse_s_frame(
24502391
}
24512392

24522393
fn parse_h_frame(
2453-
stream: &mut bbl_format::BBLDataStream,
2394+
stream: &mut BBLDataStream,
24542395
frame_def: &FrameDefinition,
24552396
debug: bool,
24562397
) -> Result<HashMap<String, i32>> {
@@ -2467,12 +2408,10 @@ fn parse_h_frame(
24672408
}
24682409

24692410
let value = match field.encoding {
2470-
bbl_format::ENCODING_SIGNED_VB => stream.read_signed_vb()?,
2471-
bbl_format::ENCODING_UNSIGNED_VB => stream.read_unsigned_vb()? as i32,
2472-
bbl_format::ENCODING_NEG_14BIT => {
2473-
-(bbl_format::sign_extend_14bit(stream.read_unsigned_vb()? as u16))
2474-
}
2475-
bbl_format::ENCODING_NULL => 0,
2411+
ENCODING_SIGNED_VB => stream.read_signed_vb()?,
2412+
ENCODING_UNSIGNED_VB => stream.read_unsigned_vb()? as i32,
2413+
ENCODING_NEG_14BIT => -(sign_extend_14bit(stream.read_unsigned_vb()? as u16)),
2414+
ENCODING_NULL => 0,
24762415
_ => {
24772416
if debug {
24782417
println!(
@@ -2494,7 +2433,7 @@ fn parse_h_frame(
24942433
// like P frames in the main parsing loop for correct GPS coordinate calculation
24952434

24962435
// Parse E frames (Event frames) - based on C reference implementation
2497-
fn parse_e_frame(stream: &mut bbl_format::BBLDataStream, debug: bool) -> Result<EventFrame> {
2436+
fn parse_e_frame(stream: &mut BBLDataStream, debug: bool) -> Result<EventFrame> {
24982437
if debug {
24992438
println!("Parsing E frame (Event frame)");
25002439
}
@@ -2660,7 +2599,7 @@ fn parse_e_frame(stream: &mut bbl_format::BBLDataStream, debug: bool) -> Result<
26602599
})
26612600
}
26622601

2663-
fn skip_frame(stream: &mut bbl_format::BBLDataStream, frame_type: char, debug: bool) -> Result<()> {
2602+
fn skip_frame(stream: &mut BBLDataStream, frame_type: char, debug: bool) -> Result<()> {
26642603
if debug {
26652604
println!("Skipping {frame_type} frame");
26662605
}

0 commit comments

Comments
 (0)