add conversions to/from {be,le,ne}_bytes

This commit is contained in:
Trevor Spiteri 2019-11-24 20:13:26 +01:00
parent aac0353bb1
commit 68b2190a86
3 changed files with 249 additions and 10 deletions

View File

@ -301,17 +301,20 @@ macro_rules! fixed {
(
$description:expr,
$Fixed:ident($Inner:ty, $LeEqU:tt, $s_nbits:expr),
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
$UInner:ty, $Signedness:tt
) => {
fixed! {
$description,
$Fixed[stringify!($Fixed)]($Inner[stringify!($Inner)], $LeEqU, $s_nbits),
$nbytes, $bytes_val, $be_bytes, $le_bytes,
$UInner, $Signedness
}
};
(
$description:expr,
$Fixed:ident[$s_fixed:expr]($Inner:ty[$s_inner:expr], $LeEqU:tt, $s_nbits:expr),
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
$UInner:ty, $Signedness:tt
) => {
comment! {
@ -380,6 +383,7 @@ assert_eq!(two_point_75.to_string(), \"2.8\");
fixed_no_frac! {
$description,
$Fixed[$s_fixed]($Inner[$s_inner], $s_nbits),
$nbytes, $bytes_val, $be_bytes, $le_bytes,
$UInner, $Signedness
}
// inherent methods that require Frac bounds, and cannot be const
@ -391,16 +395,78 @@ assert_eq!(two_point_75.to_string(), \"2.8\");
};
}
fixed! { "An eight-bit fixed-point unsigned", FixedU8(u8, LeEqU8, "8"), u8, Unsigned }
fixed! { "A 16-bit fixed-point unsigned", FixedU16(u16, LeEqU16, "16"), u16, Unsigned }
fixed! { "A 32-bit fixed-point unsigned", FixedU32(u32, LeEqU32, "32"), u32, Unsigned }
fixed! { "A 64-bit fixed-point unsigned", FixedU64(u64, LeEqU64, "64"), u64, Unsigned }
fixed! { "A 128-bit fixed-point unsigned", FixedU128(u128, LeEqU128, "128"), u128, Unsigned }
fixed! { "An eight-bit fixed-point signed", FixedI8(i8, LeEqU8, "8"), u8, Signed }
fixed! { "A 16-bit fixed-point signed", FixedI16(i16, LeEqU16, "16"), u16, Signed }
fixed! { "A 32-bit fixed-point signed", FixedI32(i32, LeEqU32, "32"), u32, Signed }
fixed! { "A 64-bit fixed-point signed", FixedI64(i64, LeEqU64, "64"), u64, Signed }
fixed! { "A 128-bit fixed-point signed", FixedI128(i128, LeEqU128, "128"), u128, Signed }
fixed! {
"An eight-bit fixed-point unsigned",
FixedU8(u8, LeEqU8, "8"),
1, "0x12", "[0x12]", "[0x12]",
u8, Unsigned
}
fixed! {
"A 16-bit fixed-point unsigned",
FixedU16(u16, LeEqU16, "16"),
2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]",
u16, Unsigned
}
fixed! {
"A 32-bit fixed-point unsigned",
FixedU32(u32, LeEqU32, "32"),
4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
u32, Unsigned
}
fixed! {
"A 64-bit fixed-point unsigned",
FixedU64(u64, LeEqU64, "64"),
8, "0x1234_5678_9ABC_DEF0",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
u64, Unsigned
}
fixed! {
"A 128-bit fixed-point unsigned",
FixedU128(u128, LeEqU128, "128"),
16, "0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, \
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
u128, Unsigned
}
fixed! {
"An eight-bit fixed-point signed",
FixedI8(i8, LeEqU8, "8"),
1, "0x12", "[0x12]", "[0x12]",
u8, Signed
}
fixed! {
"A 16-bit fixed-point signed",
FixedI16(i16, LeEqU16, "16"),
2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]",
u16, Signed
}
fixed! {
"A 32-bit fixed-point signed",
FixedI32(i32, LeEqU32, "32"),
4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]",
u32, Signed
}
fixed! {
"A 64-bit fixed-point signed",
FixedI64(i64, LeEqU64, "64"),
8, "0x1234_5678_9ABC_DEF0",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
u64, Signed
}
fixed! {
"A 128-bit fixed-point signed",
FixedI128(i128, LeEqU128, "128"),
16, "0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0",
"[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, \
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]",
"[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \
0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]",
u128, Signed
}
#[cfg(test)]
#[allow(clippy::cognitive_complexity)]

View File

@ -17,6 +17,7 @@ macro_rules! fixed_no_frac {
(
$description:expr,
$Fixed:ident[$s_fixed:expr]($Inner:ty[$s_inner:expr], $s_nbits:expr),
$nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr,
$UInner:ty, $Signedness:tt
) => {
impl<Frac> $Fixed<Frac> {
@ -95,6 +96,143 @@ assert_eq!(Fix::from_num(2).to_bits(), 0b10_0000);
}
}
comment! {
"Creates a fixed-point number from its representation
as a byte array in big endian.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::from_be_bytes(", $be_bytes, "),
Fix::from_bits(", $bytes_val, ")
);
```
";
#[inline]
pub fn from_be_bytes(bytes: [u8; $nbytes]) -> $Fixed<Frac> {
$Fixed::from_bits(<$Inner>::from_be_bytes(bytes))
}
}
comment! {
"Creates a fixed-point number from its representation
as a byte array in little endian.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
Fix::from_le_bytes(", $le_bytes, "),
Fix::from_bits(", $bytes_val, ")
);
```
";
#[inline]
pub fn from_le_bytes(bytes: [u8; $nbytes]) -> $Fixed<Frac> {
$Fixed::from_bits(<$Inner>::from_le_bytes(bytes))
}
}
comment! {
"Creates a fixed-point number from its representation
as a byte array in native endian.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
assert_eq!(
if cfg!(target_endian = \"big\") {
Fix::from_ne_bytes(", $be_bytes, ")
} else {
Fix::from_ne_bytes(", $le_bytes, ")
},
Fix::from_bits(", $bytes_val, ")
);
```
";
#[inline]
pub fn from_ne_bytes(bytes: [u8; $nbytes]) -> $Fixed<Frac> {
$Fixed::from_bits(<$Inner>::from_ne_bytes(bytes))
}
}
comment! {
"Returns the memory representation of this fixed-point
number as a byte array in big-endian byte order.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
let val = Fix::from_bits(", $bytes_val, ");
assert_eq!(
val.to_be_bytes(),
", $be_bytes, "
);
```
";
#[inline]
pub fn to_be_bytes(self) -> [u8; $nbytes] {
self.to_bits().to_be_bytes()
}
}
comment! {
"Returns the memory representation of this fixed-point
number as a byte array in little-endian byte order.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
let val = Fix::from_bits(", $bytes_val, ");
assert_eq!(
val.to_le_bytes(),
", $le_bytes, "
);
```
";
#[inline]
pub fn to_le_bytes(self) -> [u8; $nbytes] {
self.to_bits().to_le_bytes()
}
}
comment! {
"Returns the memory representation of this fixed-point
number as a byte array in native byte order.
# Examples
```rust
use fixed::{types::extra::U4, ", $s_fixed, "};
type Fix = ", $s_fixed, "<U4>;
let val = Fix::from_bits(", $bytes_val, ");
assert_eq!(
val.to_ne_bytes(),
if cfg!(target_endian = \"big\") {
", $be_bytes, "
} else {
", $le_bytes, "
}
);
```
";
#[inline]
pub fn to_ne_bytes(self) -> [u8; $nbytes] {
self.to_bits().to_ne_bytes()
}
}
comment! {
"Returns the number of ones in the binary
representation.

View File

@ -31,6 +31,7 @@ use core::{
DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
SubAssign,
},
mem,
str::FromStr,
};
#[cfg(feature = "f16")]
@ -231,6 +232,9 @@ where
/// The primitive integer underlying type.
type Bits;
/// A byte array with the same size as the type.
type Bytes;
/// The number of fractional bits.
///
/// <code>&lt;F as [Fixed]&gt;::Frac::[U32]</code> is equivalent to
@ -261,6 +265,30 @@ where
/// to the given fixed-point number.
fn to_bits(self) -> Self::Bits;
/// Creates a fixed-point number from its representation as a byte
/// array in big endian.
fn from_be_bytes(bytes: Self::Bytes) -> Self;
/// Creates a fixed-point number from its representation as a byte
/// array in little endian.
fn from_le_bytes(bytes: Self::Bytes) -> Self;
/// Creates a fixed-point number from its representation as a byte
/// array in native endian.
fn from_ne_bytes(bytes: Self::Bytes) -> Self;
/// Returns the memory representation of this fixed-point number
/// as a byte array in big-endian byte order.
fn to_be_bytes(self) -> Self::Bytes;
/// Returns the memory representation of this fixed-point number
/// as a byte array in little-endian byte order.
fn to_le_bytes(self) -> Self::Bytes;
/// Returns the memory representation of this fixed-point number
/// as a byte array in native byte order.
fn to_ne_bytes(self) -> Self::Bytes;
/// Creates a fixed-point number from another number.
///
/// Returns the same value as [`src.to_fixed()`][`to_fixed`].
@ -1398,6 +1426,7 @@ macro_rules! impl_fixed {
impl<Frac: $LeEqU> Fixed for $Fixed<Frac> {
type Bits = $Bits;
type Bytes = [u8; mem::size_of::<$Bits>()];
type Frac = Frac;
trait_delegate! { fn min_value() -> Self }
trait_delegate! { fn max_value() -> Self }
@ -1405,6 +1434,12 @@ macro_rules! impl_fixed {
trait_delegate! { fn frac_nbits() -> u32 }
trait_delegate! { fn from_bits(bits: Self::Bits) -> Self }
trait_delegate! { fn to_bits(self) -> Self::Bits }
trait_delegate! { fn from_be_bytes(bits: Self::Bytes) -> Self }
trait_delegate! { fn from_le_bytes(bits: Self::Bytes) -> Self }
trait_delegate! { fn from_ne_bytes(bits: Self::Bytes) -> Self }
trait_delegate! { fn to_be_bytes(self) -> Self::Bytes }
trait_delegate! { fn to_le_bytes(self) -> Self::Bytes }
trait_delegate! { fn to_ne_bytes(self) -> Self::Bytes }
trait_delegate! { fn from_num<Src: ToFixed>(src: Src) -> Self }
trait_delegate! { fn to_num<Dst: FromFixed>(self) -> Dst }
trait_delegate! { fn checked_from_num<Src: ToFixed>(val: Src) -> Option<Self> }