mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
fix writing larger int types in big endian
This commit is contained in:
parent
2fe6af6224
commit
b46bc881f0
3 changed files with 69 additions and 23 deletions
|
|
@ -277,7 +277,7 @@ impl_is_signed!(isize, true);
|
|||
pub trait SplitFitUsize {
|
||||
type Iter: Iterator<Item = (usize, u8)> + ExactSizeIterator + DoubleEndedIterator;
|
||||
|
||||
fn split_fit_usize<E: Endianness>(self) -> Self::Iter;
|
||||
fn split_fit_usize<E: Endianness>(self, count: u8) -> Self::Iter;
|
||||
}
|
||||
|
||||
use std::array;
|
||||
|
|
@ -288,7 +288,7 @@ macro_rules! impl_split_fit {
|
|||
impl SplitFitUsize for $type {
|
||||
type Iter = array::IntoIter<(usize, u8), 1>;
|
||||
|
||||
fn split_fit_usize<E: Endianness>(self) -> Self::Iter {
|
||||
fn split_fit_usize<E: Endianness>(self, _count: u8) -> Self::Iter {
|
||||
assert!(size_of::<Self>() < size_of::<usize>());
|
||||
[(self as usize, size_of::<Self>() as u8 * 8)].into_iter()
|
||||
}
|
||||
|
|
@ -301,9 +301,9 @@ macro_rules! impl_split_fit_signed {
|
|||
impl SplitFitUsize for $signed_type {
|
||||
type Iter = <$unsigned_type as SplitFitUsize>::Iter;
|
||||
|
||||
fn split_fit_usize<E: Endianness>(self) -> Self::Iter {
|
||||
fn split_fit_usize<E: Endianness>(self, count: u8) -> Self::Iter {
|
||||
let unsigned = <$unsigned_type>::from_ne_bytes(self.to_ne_bytes());
|
||||
unsigned.split_fit_usize::<E>()
|
||||
unsigned.split_fit_usize::<E>(count)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -320,16 +320,20 @@ impl_split_fit!(u32);
|
|||
impl SplitFitUsize for u32 {
|
||||
type Iter = array::IntoIter<(usize, u8), 2>;
|
||||
|
||||
fn split_fit_usize<E: Endianness>(self) -> Self::Iter {
|
||||
fn split_fit_usize<E: Endianness>(self, count: u8) -> Self::Iter {
|
||||
Self::Iter::new(if E::is_le() {
|
||||
[
|
||||
((self & (Self::MAX >> 8)) as usize, 24),
|
||||
((self >> 24) as usize, 8),
|
||||
]
|
||||
} else {
|
||||
let offset = Self::BITS as u8 - count;
|
||||
[
|
||||
((self >> 24) as usize, 8),
|
||||
((self & (Self::MAX >> 8)) as usize, 24),
|
||||
((self >> 24) as usize, 8u8.saturating_sub(offset)),
|
||||
(
|
||||
(self & (Self::MAX >> 8)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(8)),
|
||||
),
|
||||
]
|
||||
})
|
||||
}
|
||||
|
|
@ -340,7 +344,7 @@ impl_split_fit_signed!(i32, u32);
|
|||
impl SplitFitUsize for u64 {
|
||||
type Iter = array::IntoIter<(usize, u8), 3>;
|
||||
|
||||
fn split_fit_usize<E: Endianness>(self) -> Self::Iter {
|
||||
fn split_fit_usize<E: Endianness>(self, count: u8) -> Self::Iter {
|
||||
(if E::is_le() {
|
||||
[
|
||||
((self & (Self::MAX >> 40)) as usize, 24),
|
||||
|
|
@ -348,10 +352,17 @@ impl SplitFitUsize for u64 {
|
|||
((self >> 48) as usize, 16),
|
||||
]
|
||||
} else {
|
||||
let offset = Self::BITS as u8 - count;
|
||||
[
|
||||
((self >> 48) as usize, 16),
|
||||
((self >> 24 & (Self::MAX >> 16)) as usize, 24),
|
||||
((self & (Self::MAX >> 40)) as usize, 24),
|
||||
((self >> 48) as usize, 16u8.saturating_sub(offset)),
|
||||
(
|
||||
(self >> 24 & (Self::MAX >> 16)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(16)),
|
||||
),
|
||||
(
|
||||
(self & (Self::MAX >> 40)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(40)),
|
||||
),
|
||||
]
|
||||
})
|
||||
.into_iter()
|
||||
|
|
@ -363,7 +374,7 @@ impl_split_fit_signed!(i64, u64);
|
|||
impl SplitFitUsize for u128 {
|
||||
type Iter = array::IntoIter<(usize, u8), 6>;
|
||||
|
||||
fn split_fit_usize<E: Endianness>(self) -> Self::Iter {
|
||||
fn split_fit_usize<E: Endianness>(self, count: u8) -> Self::Iter {
|
||||
(if E::is_le() {
|
||||
[
|
||||
((self & (Self::MAX >> 104)) as usize, 24),
|
||||
|
|
@ -374,13 +385,29 @@ impl SplitFitUsize for u128 {
|
|||
((self >> 120) as usize, 8),
|
||||
]
|
||||
} else {
|
||||
let offset = Self::BITS as u8 - count;
|
||||
[
|
||||
((self >> 120) as usize, 8),
|
||||
((self >> 96 & (Self::MAX >> 8)) as usize, 24),
|
||||
((self >> 72 & (Self::MAX >> 32)) as usize, 24),
|
||||
((self >> 48 & (Self::MAX >> 56)) as usize, 24),
|
||||
((self >> 24 & (Self::MAX >> 80)) as usize, 24),
|
||||
((self & (Self::MAX >> 104)) as usize, 24),
|
||||
((self >> 120) as usize, 8u8.saturating_sub(offset)),
|
||||
(
|
||||
(self >> 96 & (Self::MAX >> 8)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(8)),
|
||||
),
|
||||
(
|
||||
(self >> 72 & (Self::MAX >> 32)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(32)),
|
||||
),
|
||||
(
|
||||
(self >> 48 & (Self::MAX >> 56)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(56)),
|
||||
),
|
||||
(
|
||||
(self >> 24 & (Self::MAX >> 80)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(80)),
|
||||
),
|
||||
(
|
||||
(self & (Self::MAX >> 104)) as usize,
|
||||
24u8.saturating_sub(offset.saturating_sub(104)),
|
||||
),
|
||||
]
|
||||
})
|
||||
.into_iter()
|
||||
|
|
@ -392,7 +419,7 @@ impl_split_fit_signed!(i128, u128);
|
|||
impl SplitFitUsize for usize {
|
||||
type Iter = array::IntoIter<(usize, u8), 2>;
|
||||
|
||||
fn split_fit_usize<E: Endianness>(self) -> Self::Iter {
|
||||
fn split_fit_usize<E: Endianness>(self, count: u8) -> Self::Iter {
|
||||
(if E::is_le() {
|
||||
[
|
||||
(
|
||||
|
|
@ -402,11 +429,12 @@ impl SplitFitUsize for usize {
|
|||
(self >> (usize::BITS - 8), 8),
|
||||
]
|
||||
} else {
|
||||
let offset = Self::BITS as u8 - count;
|
||||
[
|
||||
(self >> (usize::BITS - 8), 8),
|
||||
(self >> (usize::BITS - 8), 8u8.saturating_sub(offset)),
|
||||
(
|
||||
self & (Self::MAX >> (usize::BITS - 8)),
|
||||
usize::BITS as u8 - 8,
|
||||
self & (Self::MAX >> 8),
|
||||
(usize::BITS as u8 - 8).saturating_sub(offset.saturating_sub(8)),
|
||||
),
|
||||
]
|
||||
})
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ where
|
|||
if type_bit_size < USIZE_BITS || count <= (USIZE_BITS - (self.bit_len() % 8)) {
|
||||
self.push_bits(value.into_usize_unchecked(), count);
|
||||
} else {
|
||||
self.push_non_fit_bits(value.split_fit_usize::<E>(), count)
|
||||
self.push_non_fit_bits(value.split_fit_usize::<E>(count as u8), count)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -243,3 +243,21 @@ fn test_write_last_slice() {
|
|||
assert_eq!(0b1000, read.read_int::<u8>(4).unwrap());
|
||||
assert!(read.read_bool().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_be_long() {
|
||||
let mut bytes = vec![];
|
||||
let mut writer = BitWriteStream::new(&mut bytes, BigEndian);
|
||||
let num1 = 0b11000_00111110usize;
|
||||
let num2 = 0b1111111_11100100_00100100_11011101_00000011_11100000_01100111_11011011usize;
|
||||
writer.write_int(num1, 13).unwrap();
|
||||
writer.write_int(num2, 63).unwrap();
|
||||
|
||||
let buffer = BitReadBuffer::new(&bytes, BigEndian);
|
||||
let mut reader = BitReadStream::new(buffer);
|
||||
let num1actual = reader.read_int::<usize>(13).unwrap();
|
||||
let num2actual = reader.read_int::<usize>(63).unwrap();
|
||||
|
||||
assert_eq!(num1actual, num1);
|
||||
assert_eq!(num2actual, num2);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue