1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-03 16:44:06 +02:00

fix reading large signed ints

This commit is contained in:
Robin Appelman 2024-04-04 22:55:06 +02:00
commit efed5a68cb
3 changed files with 72 additions and 14 deletions

View file

@ -5,7 +5,7 @@ use std::marker::PhantomData;
use std::mem::size_of;
use std::ops::{BitOrAssign, BitXor, Index, Range, RangeFrom};
use num_traits::{Float, PrimInt};
use num_traits::{Float, PrimInt, WrappingSub};
use crate::endianness::Endianness;
use crate::num_traits::{IsSigned, UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
@ -360,7 +360,7 @@ where
#[inline]
pub fn read_int<T>(&self, position: usize, count: usize) -> Result<T>
where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor,
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor + WrappingSub,
{
let type_bit_size = size_of::<T>() * 8;
@ -395,7 +395,7 @@ where
#[inline]
pub unsafe fn read_int_unchecked<T>(&self, position: usize, count: usize, end: bool) -> T
where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor,
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor + WrappingSub,
{
let type_bit_size = size_of::<T>() * 8;
@ -453,14 +453,14 @@ where
fn make_signed<T>(&self, value: T, count: usize) -> T
where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor,
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor + WrappingSub,
{
if count == 0 {
T::zero()
} else if T::is_signed() {
let sign_bit = value >> (count - 1) & T::one();
if sign_bit == T::one() {
value | (T::zero() - T::one()) ^ ((T::one() << count) - T::one())
value | (T::zero() - T::one()) ^ (T::one() << count).wrapping_sub(&T::one())
} else {
value
}
@ -718,6 +718,7 @@ where
pub fn read_float<T>(&self, position: usize) -> Result<T>
where
T: Float + UncheckedPrimitiveFloat,
<T as UncheckedPrimitiveFloat>::INT: WrappingSub,
{
let type_bit_size = size_of::<T>() * 8;
if position + type_bit_size + USIZE_BIT_SIZE > self.bit_len() {
@ -745,6 +746,7 @@ where
pub unsafe fn read_float_unchecked<T>(&self, position: usize, end: bool) -> T
where
T: Float + UncheckedPrimitiveFloat,
<T as UncheckedPrimitiveFloat>::INT: WrappingSub,
{
if position & 7 == 0 {
let byte_pos = position / 8;

View file

@ -1,7 +1,7 @@
use std::mem::size_of;
use std::ops::BitOrAssign;
use num_traits::{Float, PrimInt};
use num_traits::{Float, PrimInt, WrappingSub};
use crate::endianness::Endianness;
use crate::num_traits::{IsSigned, UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
@ -141,7 +141,7 @@ where
#[inline]
pub fn read_int<T>(&mut self, count: usize) -> Result<T>
where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + WrappingSub,
{
let result = self.buffer.read_int(self.pos, count);
if result.is_ok() {
@ -154,7 +154,7 @@ where
#[inline]
pub unsafe fn read_int_unchecked<T>(&mut self, count: usize, end: bool) -> T
where
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt,
T: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + WrappingSub,
{
let result = self.buffer.read_int_unchecked(self.pos, count, end);
self.pos += count;
@ -191,6 +191,7 @@ where
pub fn read_float<T>(&mut self) -> Result<T>
where
T: Float + UncheckedPrimitiveFloat,
<T as UncheckedPrimitiveFloat>::INT: WrappingSub,
{
let count = size_of::<T>() * 8;
let result = self.buffer.read_float(self.pos);
@ -205,6 +206,7 @@ where
pub unsafe fn read_float_unchecked<T>(&mut self, end: bool) -> T
where
T: Float + UncheckedPrimitiveFloat,
<T as UncheckedPrimitiveFloat>::INT: WrappingSub,
{
let count = size_of::<T>() * 8;
let result = self.buffer.read_float_unchecked(self.pos, end);