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

simplify float handling

This commit is contained in:
Robin Appelman 2021-07-24 19:10:37 +02:00
commit 33ea27fd67
3 changed files with 25 additions and 20 deletions

View file

@ -1,21 +1,29 @@
use crate::Endianness; use crate::Endianness;
use num_traits::PrimInt;
use std::array::TryFromSliceError; use std::array::TryFromSliceError;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt::Debug;
use std::ops::{BitOrAssign, BitXor};
/// some extra number traits /// some extra number traits
/// Allow casting floats unchecked /// Allow casting floats unchecked
pub trait UncheckedPrimitiveFloat: Sized { pub trait UncheckedPrimitiveFloat: Sized {
type BYTES: AsRef<[u8]> + for<'a> TryFrom<&'a [u8], Error = TryFromSliceError>; type BYTES: AsRef<[u8]> + for<'a> TryFrom<&'a [u8], Error = TryFromSliceError>;
type INT: PrimInt + BitOrAssign + IsSigned + UncheckedPrimitiveInt + BitXor + Debug + IntoBytes;
fn from_f32_unchecked(n: f32) -> Self; fn from_f32_unchecked(n: f32) -> Self;
fn from_f64_unchecked(n: f64) -> Self; fn from_f64_unchecked(n: f64) -> Self;
fn to_bytes<E: Endianness>(self) -> Self::BYTES; fn to_bytes<E: Endianness>(self) -> Self::BYTES;
fn from_bytes<E: Endianness>(bytes: Self::BYTES) -> Self; fn from_bytes<E: Endianness>(bytes: Self::BYTES) -> Self;
fn to_int(self) -> Self::INT;
fn from_int(int: Self::INT) -> Self;
} }
impl UncheckedPrimitiveFloat for f32 { impl UncheckedPrimitiveFloat for f32 {
type BYTES = [u8; 4]; type BYTES = [u8; 4];
type INT = u32;
#[inline(always)] #[inline(always)]
fn from_f32_unchecked(n: f32) -> Self { fn from_f32_unchecked(n: f32) -> Self {
n n
@ -38,10 +46,18 @@ impl UncheckedPrimitiveFloat for f32 {
Self::from_be_bytes(bytes) Self::from_be_bytes(bytes)
} }
} }
fn to_int(self) -> Self::INT {
Self::INT::from_le_bytes(self.to_le_bytes())
}
fn from_int(int: Self::INT) -> Self {
Self::from_le_bytes(int.to_le_bytes())
}
} }
impl UncheckedPrimitiveFloat for f64 { impl UncheckedPrimitiveFloat for f64 {
type BYTES = [u8; 8]; type BYTES = [u8; 8];
type INT = u64;
#[inline(always)] #[inline(always)]
fn from_f32_unchecked(n: f32) -> Self { fn from_f32_unchecked(n: f32) -> Self {
n as f64 n as f64
@ -64,6 +80,12 @@ impl UncheckedPrimitiveFloat for f64 {
Self::from_be_bytes(bytes) Self::from_be_bytes(bytes)
} }
} }
fn to_int(self) -> Self::INT {
Self::INT::from_le_bytes(self.to_le_bytes())
}
fn from_int(int: Self::INT) -> Self {
Self::from_le_bytes(int.to_le_bytes())
}
} }
/// Allow casting integers unchecked /// Allow casting integers unchecked

View file

@ -744,17 +744,8 @@ where
.unwrap(); .unwrap();
T::from_bytes::<E>(bytes) T::from_bytes::<E>(bytes)
} else { } else {
if size_of::<T>() == 4 { let int = self.read_int_unchecked(position, size_of::<T>() * 8, end);
let int = if size_of::<T>() < USIZE_SIZE { T::from_int(int)
self.read_fit_usize::<u32>(position, 32, end)
} else {
self.read_no_fit_usize::<u32>(position, 32, end)
};
T::from_f32_unchecked(f32::from_bits(int))
} else {
let int = self.read_no_fit_usize::<u64>(position, 64, end);
T::from_f64_unchecked(f64::from_bits(int))
}
} }
} }

View file

@ -177,15 +177,7 @@ where
let bytes = value.to_bytes::<E>(); let bytes = value.to_bytes::<E>();
self.buffer.extends_from_slice(bytes.as_ref()); self.buffer.extends_from_slice(bytes.as_ref());
} else { } else {
if size_of::<T>() == 4 { self.write_int(value.to_int(), size_of::<T>() * 8)?;
if size_of::<T>() < USIZE_SIZE {
self.push_bits(value.to_f32().unwrap().to_bits() as usize, 32);
} else {
self.push_non_fit_bits(value.to_f32().unwrap().to_bits().into_bytes(), 32)
};
} else {
self.push_non_fit_bits(value.to_f64().unwrap().to_bits().into_bytes(), 64)
}
} }
Ok(()) Ok(())