Skip to content

Commit c86da17

Browse files
committed
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
1 parent e20e467 commit c86da17

5 files changed

Lines changed: 152 additions & 114 deletions

File tree

src/bbl_format.rs

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
use anyhow::Result;
2+
use bbl_parser::parser::helpers::{
3+
sign_extend_16bit, sign_extend_24bit, sign_extend_2bit, sign_extend_4bit, sign_extend_6bit,
4+
sign_extend_8bit,
5+
};
26
use std::collections::HashMap;
37

8+
// Re-export sign_extend_14bit for backward compatibility with main.rs
9+
pub use bbl_parser::parser::helpers::sign_extend_14bit;
10+
411
// BBL Encoding constants - directly from JavaScript reference
512
pub const ENCODING_SIGNED_VB: u8 = 0;
613
pub const ENCODING_UNSIGNED_VB: u8 = 1;
@@ -266,58 +273,6 @@ impl<'a> BBLDataStream<'a> {
266273
}
267274
}
268275

269-
// Sign extension functions - exact replicas of JavaScript implementations
270-
pub fn sign_extend_2bit(value: u8) -> i32 {
271-
let val = value as i32;
272-
if (val & 0x02) != 0 {
273-
val | !0x03
274-
} else {
275-
val & 0x03
276-
}
277-
}
278-
279-
pub fn sign_extend_4bit(value: u8) -> i32 {
280-
let val = value as i32;
281-
if (val & 0x08) != 0 {
282-
val | !0x0f
283-
} else {
284-
val & 0x0f
285-
}
286-
}
287-
288-
pub fn sign_extend_6bit(value: u8) -> i32 {
289-
let val = value as i32;
290-
if (val & 0x20) != 0 {
291-
val | !0x3f
292-
} else {
293-
val & 0x3f
294-
}
295-
}
296-
297-
pub fn sign_extend_8bit(value: u8) -> i32 {
298-
value as i8 as i32
299-
}
300-
301-
pub fn sign_extend_16bit(value: u16) -> i32 {
302-
value as i16 as i32
303-
}
304-
305-
pub fn sign_extend_24bit(value: u32) -> i32 {
306-
if (value & 0x800000) != 0 {
307-
(value | 0xff000000) as i32
308-
} else {
309-
(value & 0x7fffff) as i32
310-
}
311-
}
312-
313-
pub fn sign_extend_14bit(value: u16) -> i32 {
314-
if (value & 0x2000) != 0 {
315-
-((value & 0x1fff) as i32)
316-
} else {
317-
(value & 0x1fff) as i32
318-
}
319-
}
320-
321276
#[allow(clippy::too_many_arguments)]
322277
#[allow(dead_code)]
323278
pub fn apply_predictor(

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/parser/helpers.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//! Helper functions for BBL parsing
2+
//!
3+
//! This module provides sign extension functions used for decoding various
4+
//! fixed-width signed values from the blackbox binary format.
5+
6+
/// Sign-extend a 2-bit value to i32
7+
pub fn sign_extend_2bit(value: u8) -> i32 {
8+
let val = value as i32;
9+
if (val & 0x02) != 0 {
10+
val | !0x03
11+
} else {
12+
val & 0x03
13+
}
14+
}
15+
16+
/// Sign-extend a 4-bit value to i32
17+
pub fn sign_extend_4bit(value: u8) -> i32 {
18+
let val = value as i32;
19+
if (val & 0x08) != 0 {
20+
val | !0x0f
21+
} else {
22+
val & 0x0f
23+
}
24+
}
25+
26+
/// Sign-extend a 6-bit value to i32
27+
pub fn sign_extend_6bit(value: u8) -> i32 {
28+
let val = value as i32;
29+
if (val & 0x20) != 0 {
30+
val | !0x3f
31+
} else {
32+
val & 0x3f
33+
}
34+
}
35+
36+
/// Sign-extend an 8-bit value to i32
37+
pub fn sign_extend_8bit(value: u8) -> i32 {
38+
value as i8 as i32
39+
}
40+
41+
/// Sign-extend a 16-bit value to i32
42+
pub fn sign_extend_16bit(value: u16) -> i32 {
43+
value as i16 as i32
44+
}
45+
46+
/// Sign-extend a 24-bit value to i32
47+
pub fn sign_extend_24bit(value: u32) -> i32 {
48+
if (value & 0x800000) != 0 {
49+
(value | 0xff000000) as i32
50+
} else {
51+
(value & 0x7fffff) as i32
52+
}
53+
}
54+
55+
/// Sign-extend a 14-bit value to i32 (sign-magnitude format)
56+
/// Bit 13 indicates sign, bits 0-12 are the magnitude.
57+
/// Returns negative value if sign bit is set.
58+
pub fn sign_extend_14bit(value: u16) -> i32 {
59+
if (value & 0x2000) != 0 {
60+
-((value & 0x1fff) as i32)
61+
} else {
62+
(value & 0x1fff) as i32
63+
}
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
use super::*;
69+
70+
#[test]
71+
fn test_sign_extend_2bit() {
72+
assert_eq!(sign_extend_2bit(0), 0);
73+
assert_eq!(sign_extend_2bit(1), 1);
74+
assert_eq!(sign_extend_2bit(2), -2);
75+
assert_eq!(sign_extend_2bit(3), -1);
76+
}
77+
78+
#[test]
79+
fn test_sign_extend_4bit() {
80+
assert_eq!(sign_extend_4bit(0), 0);
81+
assert_eq!(sign_extend_4bit(7), 7);
82+
assert_eq!(sign_extend_4bit(8), -8);
83+
assert_eq!(sign_extend_4bit(15), -1);
84+
}
85+
86+
#[test]
87+
fn test_sign_extend_6bit() {
88+
assert_eq!(sign_extend_6bit(0), 0);
89+
assert_eq!(sign_extend_6bit(31), 31);
90+
assert_eq!(sign_extend_6bit(32), -32);
91+
assert_eq!(sign_extend_6bit(63), -1);
92+
}
93+
94+
#[test]
95+
fn test_sign_extend_8bit() {
96+
assert_eq!(sign_extend_8bit(0), 0);
97+
assert_eq!(sign_extend_8bit(127), 127);
98+
assert_eq!(sign_extend_8bit(128), -128);
99+
assert_eq!(sign_extend_8bit(255), -1);
100+
}
101+
102+
#[test]
103+
fn test_sign_extend_16bit() {
104+
assert_eq!(sign_extend_16bit(0), 0);
105+
assert_eq!(sign_extend_16bit(32767), 32767);
106+
assert_eq!(sign_extend_16bit(32768), -32768);
107+
assert_eq!(sign_extend_16bit(65535), -1);
108+
}
109+
110+
#[test]
111+
fn test_sign_extend_24bit() {
112+
assert_eq!(sign_extend_24bit(0), 0);
113+
assert_eq!(sign_extend_24bit(0x7FFFFF), 0x7FFFFF);
114+
assert_eq!(sign_extend_24bit(0x800000), -8388608);
115+
assert_eq!(sign_extend_24bit(0xFFFFFF), -1);
116+
}
117+
118+
#[test]
119+
fn test_sign_extend_14bit() {
120+
// Positive values (bit 13 clear)
121+
assert_eq!(sign_extend_14bit(0), 0);
122+
assert_eq!(sign_extend_14bit(1), 1);
123+
assert_eq!(sign_extend_14bit(0x1FFF), 0x1FFF); // 8191
124+
125+
// Negative values (bit 13 set)
126+
assert_eq!(sign_extend_14bit(0x2000), 0); // -0
127+
assert_eq!(sign_extend_14bit(0x2001), -1);
128+
assert_eq!(sign_extend_14bit(0x3FFF), -8191);
129+
}
130+
}

src/parser/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub mod event;
33
pub mod frame;
44
pub mod gps;
55
pub mod header;
6+
pub mod helpers;
67
pub mod main;
78
pub mod stream;
89

@@ -11,5 +12,6 @@ pub use event::*;
1112
pub use frame::*;
1213
pub use gps::*;
1314
pub use header::*;
15+
pub use helpers::*;
1416
pub use main::*;
1517
pub use stream::*;

src/parser/stream.rs

Lines changed: 13 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use crate::parser::helpers::{
2+
sign_extend_14bit, sign_extend_16bit, sign_extend_24bit, sign_extend_2bit, sign_extend_4bit,
3+
sign_extend_6bit, sign_extend_8bit,
4+
};
15
use anyhow::Result;
26

37
/// BBL data stream for reading binary data
@@ -226,82 +230,32 @@ impl<'a> BBLDataStream<'a> {
226230
/// Returns the negated value to match blackbox_decode behavior.
227231
pub fn read_neg_14bit(&mut self) -> Result<i32> {
228232
let unsigned = self.read_unsigned_vb()? as u16;
229-
Ok(-sign_extend_14bit_sign_magnitude(unsigned))
230-
}
231-
}
232-
233-
/// Sign-magnitude 14-bit encoding (matches bbl_format::sign_extend_14bit and blackbox_decode)
234-
/// Bit 13 indicates sign, bits 0-12 are the magnitude
235-
fn sign_extend_14bit_sign_magnitude(value: u16) -> i32 {
236-
if (value & 0x2000) != 0 {
237-
-((value & 0x1fff) as i32)
238-
} else {
239-
(value & 0x1fff) as i32
240-
}
241-
}
242-
243-
// Sign extension helper functions - exact replicas of JavaScript implementation
244-
fn sign_extend_2bit(value: u8) -> i32 {
245-
if (value & 0x02) != 0 {
246-
(value as i32) | !0x03
247-
} else {
248-
value as i32
249-
}
250-
}
251-
252-
fn sign_extend_4bit(value: u8) -> i32 {
253-
if (value & 0x08) != 0 {
254-
(value as i32) | !0x0f
255-
} else {
256-
value as i32
257-
}
258-
}
259-
260-
fn sign_extend_6bit(value: u8) -> i32 {
261-
if (value & 0x20) != 0 {
262-
(value as i32) | !0x3f
263-
} else {
264-
value as i32
265-
}
266-
}
267-
268-
fn sign_extend_8bit(value: u8) -> i32 {
269-
value as i8 as i32
270-
}
271-
272-
fn sign_extend_16bit(value: u16) -> i32 {
273-
value as i16 as i32
274-
}
275-
276-
fn sign_extend_24bit(value: u32) -> i32 {
277-
if (value & 0x800000) != 0 {
278-
(value as i32) | !0xffffff
279-
} else {
280-
value as i32
233+
Ok(-sign_extend_14bit(unsigned))
281234
}
282235
}
283236

284237
#[cfg(test)]
285238
mod tests {
286239
use super::*;
240+
use crate::parser::helpers::sign_extend_14bit;
287241

288242
#[test]
289243
fn test_sign_extend_14bit_sign_magnitude_positive() {
290244
// Positive values have bit 13 = 0 (sign bit clear)
291-
assert_eq!(sign_extend_14bit_sign_magnitude(0x0000), 0); // 0
292-
assert_eq!(sign_extend_14bit_sign_magnitude(0x0001), 1); // 1
293-
assert_eq!(sign_extend_14bit_sign_magnitude(0x1FFF), 0x1FFF); // 8191 (max positive magnitude)
245+
assert_eq!(sign_extend_14bit(0x0000), 0); // 0
246+
assert_eq!(sign_extend_14bit(0x0001), 1); // 1
247+
assert_eq!(sign_extend_14bit(0x1FFF), 0x1FFF); // 8191 (max positive magnitude)
294248
}
295249

296250
#[test]
297251
fn test_sign_extend_14bit_sign_magnitude_negative() {
298252
// Negative values have bit 13 = 1 (sign bit set), magnitude in bits 0-12
299253
// 0x2000 = bit 13 set, magnitude 0 -> returns -0 = 0 (actually negative zero)
300-
assert_eq!(sign_extend_14bit_sign_magnitude(0x2000), 0); // -0
301-
// 0x2001 = bit 13 set, magnitude 1 -> returns -1
302-
assert_eq!(sign_extend_14bit_sign_magnitude(0x2001), -1);
254+
assert_eq!(sign_extend_14bit(0x2000), 0); // -0
255+
// 0x2001 = bit 13 set, magnitude 1 -> returns -1
256+
assert_eq!(sign_extend_14bit(0x2001), -1);
303257
// 0x3FFF = bit 13 set, magnitude 0x1FFF (8191) -> returns -8191
304-
assert_eq!(sign_extend_14bit_sign_magnitude(0x3FFF), -8191);
258+
assert_eq!(sign_extend_14bit(0x3FFF), -8191);
305259
}
306260

307261
#[test]

0 commit comments

Comments
 (0)