mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 08:34:07 +02:00
fix 2's-completement encoding for non full with signed ints
This commit is contained in:
parent
f190ccf320
commit
2fd2b49810
3 changed files with 22 additions and 44 deletions
|
|
@ -12,7 +12,7 @@ name = "bitstream_reader_derive"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = { version = "0.15" }
|
syn = "0.15"
|
||||||
quote = "0.6"
|
quote = "0.6"
|
||||||
proc-macro2 = "0.4"
|
proc-macro2 = "0.4"
|
||||||
syn_util = "0.3"
|
syn_util = "0.3"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::ops::BitOrAssign;
|
use std::ops::{BitOrAssign, BitXor};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use num_traits::{Float, PrimInt};
|
use num_traits::{Float, PrimInt};
|
||||||
|
|
@ -190,7 +190,7 @@ where
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_int<T>(&self, position: usize, count: usize) -> Result<T>
|
pub fn read_int<T>(&self, position: usize, count: usize) -> Result<T>
|
||||||
where
|
where
|
||||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor,
|
||||||
{
|
{
|
||||||
let type_bit_size = size_of::<T>() * 8;
|
let type_bit_size = size_of::<T>() * 8;
|
||||||
|
|
||||||
|
|
@ -227,7 +227,7 @@ where
|
||||||
self.read_no_fit_usize(position, count)
|
self.read_no_fit_usize(position, count)
|
||||||
};
|
};
|
||||||
|
|
||||||
if count == type_bit_size && fit_usize {
|
if count == type_bit_size {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
} else {
|
||||||
Ok(self.make_signed(value, count))
|
Ok(self.make_signed(value, count))
|
||||||
|
|
@ -278,13 +278,15 @@ where
|
||||||
|
|
||||||
fn make_signed<T>(&self, value: T, count: usize) -> T
|
fn make_signed<T>(&self, value: T, count: usize) -> T
|
||||||
where
|
where
|
||||||
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
|
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor,
|
||||||
{
|
{
|
||||||
if T::is_signed() {
|
if T::is_signed() {
|
||||||
let sign_bit = value >> (count - 1) & T::one();
|
let sign_bit = value >> (count - 1) & T::one();
|
||||||
let absolute_value = value & !(T::max_value() << (count - 1));
|
if sign_bit == T::one() {
|
||||||
let sign = T::one() - sign_bit - sign_bit;
|
value | (T::zero() - T::one()) ^ ((T::one() << count) - T::one())
|
||||||
absolute_value * sign
|
} else {
|
||||||
|
value
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ fn read_u64_be() {
|
||||||
fn read_i8_le() {
|
fn read_i8_le() {
|
||||||
let buffer = BitBuffer::new(BYTES.to_vec(), LittleEndian);
|
let buffer = BitBuffer::new(BYTES.to_vec(), LittleEndian);
|
||||||
|
|
||||||
assert_eq!(buffer.read_int::<i8>(0, 3).unwrap(), -0b01);
|
assert_eq!(buffer.read_int::<i8>(0, 3).unwrap(), -0b11);
|
||||||
assert_eq!(buffer.read_int::<i8>(0, 8).unwrap(), -0b100_1011);
|
assert_eq!(buffer.read_int::<i8>(0, 8).unwrap(), -0b100_1011);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,7 +132,7 @@ fn read_i8_be() {
|
||||||
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
||||||
|
|
||||||
assert_eq!(buffer.read_int::<i8>(1, 2).unwrap(), 0b1);
|
assert_eq!(buffer.read_int::<i8>(1, 2).unwrap(), 0b1);
|
||||||
assert_eq!(buffer.read_int::<i8>(0, 3).unwrap(), -0b01);
|
assert_eq!(buffer.read_int::<i8>(0, 3).unwrap(), -0b11);
|
||||||
assert_eq!(buffer.read_int::<i8>(0, 8).unwrap(), -0b100_1011);
|
assert_eq!(buffer.read_int::<i8>(0, 8).unwrap(), -0b100_1011);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,7 +141,7 @@ fn read_i16_le() {
|
||||||
let buffer = BitBuffer::new(BYTES.to_vec(), LittleEndian);
|
let buffer = BitBuffer::new(BYTES.to_vec(), LittleEndian);
|
||||||
|
|
||||||
assert_eq!(buffer.read_int::<i16>(6, 12).unwrap(), 0b0_0110_1010_10);
|
assert_eq!(buffer.read_int::<i16>(6, 12).unwrap(), 0b0_0110_1010_10);
|
||||||
assert_eq!(buffer.read_int::<i16>(6, 13).unwrap(), -0b00_0110_1010_10);
|
assert_eq!(buffer.read_int::<i16>(6, 13).unwrap(), -0b11_1001_0101_10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -149,7 +149,7 @@ fn read_i16_be() {
|
||||||
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
||||||
|
|
||||||
assert_eq!(buffer.read_int::<i16>(6, 12).unwrap(), 0b1_0110_1010_10);
|
assert_eq!(buffer.read_int::<i16>(6, 12).unwrap(), 0b1_0110_1010_10);
|
||||||
assert_eq!(buffer.read_int::<i16>(7, 12).unwrap(), -0b0110_1010_101);
|
assert_eq!(buffer.read_int::<i16>(7, 12).unwrap(), -0b1001_0101_011);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -160,56 +160,32 @@ fn read_i32_le() {
|
||||||
buffer.read_int::<i32>(6, 24).unwrap(),
|
buffer.read_int::<i32>(6, 24).unwrap(),
|
||||||
0b1_1001_1010_1100_0110_1010_10
|
0b1_1001_1010_1100_0110_1010_10
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(buffer.read_int::<i32>(6, 26).unwrap(), -26824278);
|
||||||
buffer.read_int::<i32>(6, 26).unwrap(),
|
|
||||||
-0b001_1001_1010_1100_0110_1010_10
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_i32_be() {
|
fn read_i32_be() {
|
||||||
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(buffer.read_int::<i32>(7, 24).unwrap(), -4893108);
|
||||||
buffer.read_int::<i32>(7, 24).unwrap(),
|
|
||||||
-0b0110_1010_1010_1100_1001_100
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_i64_le() {
|
fn read_i64_le() {
|
||||||
let buffer = BitBuffer::new(BYTES.to_vec(), LittleEndian);
|
let buffer = BitBuffer::new(BYTES.to_vec(), LittleEndian);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(buffer.read_int::<i64>(6, 34).unwrap(), -6871928406);
|
||||||
buffer.read_int::<i64>(6, 34).unwrap(),
|
assert_eq!(buffer.read_int::<i64>(6, 59).unwrap(), -27471957726940758);
|
||||||
-0b001_1001_1001_1001_1010_1100_0110_1010_10
|
assert_eq!(buffer.read_int::<i64>(1, 64).unwrap(), -879102647262104230);
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
buffer.read_int::<i64>(6, 59).unwrap(),
|
|
||||||
-0b1110_01111001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_10
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
buffer.read_int::<i64>(1, 64).unwrap(),
|
|
||||||
-0b1110_01111001_1001_1001_1001_1001_1001_1001_1001_1010_1100_0110_1010_1011_010
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_i64_be() {
|
fn read_i64_be() {
|
||||||
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
let buffer = BitBuffer::new(BYTES.to_vec(), BigEndian);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(buffer.read_int::<i64>(7, 34).unwrap(), -5010541773);
|
||||||
buffer.read_int::<i64>(7, 34).unwrap(),
|
assert_eq!(buffer.read_int::<i64>(7, 60).unwrap(), -336251766397153476);
|
||||||
-0b0110_1010_1010_1100_1001_1001_1001_1001_1
|
assert_eq!(buffer.read_int::<i64>(7, 64).unwrap(), -5380028262354455604);
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
buffer.read_int::<i64>(7, 60).unwrap(),
|
|
||||||
-0b0110_1010_1010_1100_1001_1001_1001_1001_1001_1001_1001_1001_1110_0111_100
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
buffer.read_int::<i64>(7, 64).unwrap(),
|
|
||||||
-0b0110_1010_1010_1100_1001_1001_1001_1001_1001_1001_1001_1001_1110_0111_1001_100
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue