@@ -220,17 +220,23 @@ impl<'a> BBLDataStream<'a> {
220220 Ok ( ( ) )
221221 }
222222
223- /// Read negative 14-bit encoding
224- /// Reads an unsigned variable byte and interprets it as a 14-bit two's complement signed value.
225- /// The value is masked to 14 bits (0x3FFF), with bit 13 serving as the sign bit .
226- /// Negative values (sign bit set) are sign-extended to i32 .
223+ /// Read negative 14-bit encoding (sign-magnitude format)
224+ /// Reads an unsigned variable byte and interprets it as a 14-bit sign-magnitude value.
225+ /// Bit 13 is the sign bit, bits 0-12 are the magnitude .
226+ /// Returns the negated value to match blackbox_decode behavior .
227227 pub fn read_neg_14bit ( & mut self ) -> Result < i32 > {
228- let unsigned = self . read_unsigned_vb ( ) ?;
228+ let unsigned = self . read_unsigned_vb ( ) ? as u16 ;
229+ Ok ( -sign_extend_14bit_sign_magnitude ( unsigned) )
230+ }
231+ }
229232
230- // Mask to 14 bits and perform sign-extension
231- // If bit 13 is set, the value is negative and needs sign-extension
232- let masked = ( unsigned & 0x3FFF ) as u16 ;
233- Ok ( sign_extend_14bit_twos_complement ( masked) )
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
234240 }
235241}
236242
@@ -263,16 +269,6 @@ fn sign_extend_8bit(value: u8) -> i32 {
263269 value as i8 as i32
264270}
265271
266- // Two's complement sign extension for 14-bit values (distinct from bbl_format.rs::sign_extend_14bit
267- // which uses sign-magnitude encoding)
268- fn sign_extend_14bit_twos_complement ( value : u16 ) -> i32 {
269- if ( value & 0x2000 ) != 0 {
270- ( value as i32 ) | !0x3fff
271- } else {
272- ( value & 0x3fff ) as i32
273- }
274- }
275-
276272fn sign_extend_16bit ( value : u16 ) -> i32 {
277273 value as i16 as i32
278274}
@@ -290,70 +286,71 @@ mod tests {
290286 use super :: * ;
291287
292288 #[ test]
293- fn test_sign_extend_14bit_positive ( ) {
294- // Positive values have bit 13 = 0
295- assert_eq ! ( sign_extend_14bit_twos_complement ( 0x0000 ) , 0 ) ; // 0
296- assert_eq ! ( sign_extend_14bit_twos_complement ( 0x0001 ) , 1 ) ; // 1
297- assert_eq ! ( sign_extend_14bit_twos_complement ( 0x1FFF ) , 0x1FFF ) ; // 8191 (max positive)
289+ fn test_sign_extend_14bit_sign_magnitude_positive ( ) {
290+ // 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 )
298294 }
299295
300296 #[ test]
301- fn test_sign_extend_14bit_negative ( ) {
302- // Negative values have bit 13 = 1, sign extended to all upper bits
303- assert_eq ! ( sign_extend_14bit_twos_complement( 0x2000 ) , -8192 ) ; // -8192 (min negative)
304- assert_eq ! ( sign_extend_14bit_twos_complement( 0x3FFF ) , -1 ) ; // -1
305- assert_eq ! ( sign_extend_14bit_twos_complement( 0x2001 ) , -8191 ) ; // -8191
297+ fn test_sign_extend_14bit_sign_magnitude_negative ( ) {
298+ // Negative values have bit 13 = 1 (sign bit set), magnitude in bits 0-12
299+ // 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 ) ;
303+ // 0x3FFF = bit 13 set, magnitude 0x1FFF (8191) -> returns -8191
304+ assert_eq ! ( sign_extend_14bit_sign_magnitude( 0x3FFF ) , -8191 ) ;
306305 }
307306
308307 #[ test]
309308 fn test_read_neg_14bit_positive ( ) {
310309 // Test reading positive 14-bit value from variable byte encoding
311310 // VB encoding of 100 is [100] (single byte since 100 < 128)
311+ // sign_extend_14bit_sign_magnitude(100) = 100 (bit 13 not set)
312+ // read_neg_14bit returns -100 (negation)
312313 let data = vec ! [ 100u8 ] ;
313314 let mut stream = BBLDataStream :: new ( & data) ;
314- assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , 100 ) ;
315+ // The function returns the negation: -sign_extend_14bit_sign_magnitude(100) = -100
316+ assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , -100 ) ;
315317 }
316318
317319 #[ test]
318320 fn test_read_neg_14bit_negative ( ) {
319- // Test reading negative 14-bit value
320- // 14-bit value -1 (0x3FFF in two's complement)
321- // VB encode 0x3FFF: 0x3FFF = 16383
322- // 16383 in VB: 0xFF (127 + continuation), 0x7F (127, final) = 127 + 127*128 = 16383
323- let data = vec ! [ 0xFF , 0x7Fu8 ] ;
321+ // Test reading value with sign bit set
322+ // VB encode 0x2001 = 8193: 0x81 (1 + continuation), 0x40 (64, final) = 1 + 64*128 = 8193
323+ let data = vec ! [ 0x81 , 0x40u8 ] ;
324324 let mut stream = BBLDataStream :: new ( & data) ;
325- assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , -1 ) ;
325+ // 0x2001: bit 13 set, magnitude = 1, sign_extend returns -1
326+ // read_neg_14bit returns -(-1) = 1
327+ assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , 1 ) ;
326328 }
327329
328330 #[ test]
329331 fn test_read_neg_14bit_boundary ( ) {
330332 // Test boundary values
331- // Max positive: 0x1FFF (8191)
332- // VB encode 0x1FFF: 0xFF (127 + continuation), 0x3F (63, final) = 127 + 63*128 = 8191
333- let data = vec ! [ 0xFF , 0x3Fu8 ] ;
333+ // Value 0: VB = [0], sign_extend_14bit(0) = 0, read_neg_14bit returns -0 = 0
334+ let data = vec ! [ 0u8 ] ;
334335 let mut stream = BBLDataStream :: new ( & data) ;
335- assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , 8191 ) ;
336-
337- // Min negative: 0x2000 (-8192)
338- // VB encode 0x2000: 0x80 (0 + continuation), 0x20 (32, final) = 0 + 32*128 = 4096
339- // But 0x2000 & 0x3FFF = 0x2000, and bit 13 is set, so it's negative
340- // Actually we need the full 14-bit value 0x2000 = 8192
341- // In VB that's: 0x80, 0x40 = 0 + 64*128 = 8192
342- let data = vec ! [ 0x80 , 0x40u8 ] ;
336+ assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , 0 ) ;
337+
338+ // Max magnitude positive (no sign): 0x1FFF = 8191
339+ // VB encode 0x1FFF: 0xFF, 0x3F = 127 + 63*128 = 8191
340+ // sign_extend returns 8191, read_neg_14bit returns -8191
341+ let data = vec ! [ 0xFF , 0x3Fu8 ] ;
343342 let mut stream = BBLDataStream :: new ( & data) ;
344- assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , -8192 ) ;
343+ assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , -8191 ) ;
345344 }
346345
347346 #[ test]
348- fn test_read_neg_14bit_masks_14_bits ( ) {
349- // Verify that only lower 14 bits are used even if VB encodes more
350- // If VB reads a value > 0x3FFF, only lower 14 bits are used
351- // Encode 0x1FFFFF (large value), which masks to 0x3FFF = -1
352- // VB encode 0x1FFFFF: 0xFF, 0xFF, 0x7F = 127 + 127*128 + 127*128^2
353- let data = vec ! [ 0xFF , 0xFF , 0x7Fu8 ] ;
347+ fn test_read_neg_14bit_with_sign_bit ( ) {
348+ // When sign bit (bit 13) is set, sign_extend returns negative, then we negate again
349+ // 0x2001 encodes as VB: 0x81, 0x40 = 1 + 64*128 = 8193
350+ // sign_extend_14bit_sign_magnitude(0x2001) = -1 (sign bit set, magnitude 1)
351+ // read_neg_14bit returns -(-1) = 1
352+ let data = vec ! [ 0x81 , 0x40u8 ] ;
354353 let mut stream = BBLDataStream :: new ( & data) ;
355- let result = stream. read_neg_14bit ( ) . unwrap ( ) ;
356- // 0x1FFFFF & 0x3FFF = 0x3FFF, which is -1 in 14-bit two's complement
357- assert_eq ! ( result, -1 ) ;
354+ assert_eq ! ( stream. read_neg_14bit( ) . unwrap( ) , 1 ) ;
358355 }
359356}
0 commit comments