From 25655ae2156b201d4e3658e99c2c6c835d81a509 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 24 Feb 2021 13:31:40 +0100 Subject: [PATCH] add methods: {from,to}_{be,le}, swap_bytes, reverse_bits --- README.md | 10 ++++ RELEASES.md | 10 ++++ src/lib.rs | 26 +++++---- src/macros_no_frac.rs | 128 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 161 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 500e097..a5db651 100644 --- a/README.md +++ b/README.md @@ -81,11 +81,21 @@ The conversions supported cover the following cases. ### Version 1.7.0 news (unreleased) + * The following methods were added to all fixed-point numbers: + * [`from_be`][f-fb-1-7], [`from_le`][f-fl-1-7] + * [`to_be`][f-tb-1-7], [`to_le`][f-tl-1-7] + * [`swap_bytes`][f-sb-1-7], [`reverse_bits`][f-rb-1-7] * For the experimental feature [`num-traits`][feat-exp-1-7], the following traits were implemented where applicable: * [`OverflowingAdd`][nt-0-2-oa], [`OverflowingSub`][nt-0-2-os], [`OverflowingMul`][nt-0-2-om] +[f-fb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.from_be +[f-fl-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.from_le +[f-rb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.reverse_bits +[f-sb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.swap_bytes +[f-tb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.to_be +[f-tl-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.to_le [feat-exp-1-7]: https://tspiteri.gitlab.io/fixed/dev/fixed/#experimental-optional-features [nt-0-2-oa]: https://docs.rs/num-traits/^0.2/num_traits/ops/overflowing/trait.OverflowingAdd.html [nt-0-2-om]: https://docs.rs/num-traits/^0.2/num_traits/ops/overflowing/trait.OverflowingMul.html diff --git a/RELEASES.md b/RELEASES.md index 5788cea..c65b981 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -8,11 +8,21 @@ as-is, without any warranty. --> Version 1.7.0 (unreleased) ========================== + * The following methods were added to all fixed-point numbers: + * [`from_be`][f-fb-1-7], [`from_le`][f-fl-1-7] + * [`to_be`][f-tb-1-7], [`to_le`][f-tl-1-7] + * [`swap_bytes`][f-sb-1-7], [`reverse_bits`][f-rb-1-7] * For the experimental feature [`num-traits`][feat-exp-1-7], the following traits were implemented where applicable: * [`OverflowingAdd`][nt-0-2-oa], [`OverflowingSub`][nt-0-2-os], [`OverflowingMul`][nt-0-2-om] +[f-fb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.from_be +[f-fl-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.from_le +[f-rb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.reverse_bits +[f-sb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.swap_bytes +[f-tb-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.to_be +[f-tl-1-7]: https://docs.rs/fixed/~1.6/fixed/struct.FixedI32.html#method.to_le [feat-exp-1-7]: https://tspiteri.gitlab.io/fixed/dev/fixed/#experimental-optional-features [nt-0-2-oa]: https://docs.rs/num-traits/^0.2/num_traits/ops/overflowing/trait.OverflowingAdd.html [nt-0-2-om]: https://docs.rs/num-traits/^0.2/num_traits/ops/overflowing/trait.OverflowingMul.html diff --git a/src/lib.rs b/src/lib.rs index 21e8b11..906443d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -377,7 +377,7 @@ macro_rules! fixed { $Inner:ty, $LeEqU:tt, $s_nbits:expr, $s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr ), - $nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr, + $nbytes:expr, $bytes_val:expr, $rev_bytes_val:expr, $be_bytes:expr, $le_bytes:expr, $UFixed:ident, $UInner:ty, $Signedness:tt, $LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt, $Double:ident, $DoubleInner:ty, $HasDouble:tt @@ -388,7 +388,7 @@ macro_rules! fixed { $Inner[stringify!($Inner)], $LeEqU, $s_nbits, $s_nbits_m1, $s_nbits_m2, $s_nbits_m3, $s_nbits_m4 ), - $nbytes, $bytes_val, $be_bytes, $le_bytes, + $nbytes, $bytes_val, $rev_bytes_val, $be_bytes, $le_bytes, $UFixed[stringify!($UFixed)], $UInner, $Signedness, $LeEqU_C0, $LeEqU_C1, $LeEqU_C2, $LeEqU_C3, $Double, $DoubleInner, $HasDouble @@ -400,7 +400,7 @@ macro_rules! fixed { $Inner:ty[$s_inner:expr], $LeEqU:tt, $s_nbits:expr, $s_nbits_m1:expr, $s_nbits_m2:expr, $s_nbits_m3:expr, $s_nbits_m4:expr ), - $nbytes:expr, $bytes_val:expr, $be_bytes:expr, $le_bytes:expr, + $nbytes:expr, $bytes_val:expr, $rev_bytes_val:expr, $be_bytes:expr, $le_bytes:expr, $UFixed:ident[$s_ufixed:expr], $UInner:ty, $Signedness:tt, $LeEqU_C0:tt, $LeEqU_C1:tt, $LeEqU_C2:tt, $LeEqU_C3:tt, $Double:ident, $DoubleInner:ty, $HasDouble:tt @@ -470,7 +470,7 @@ assert_eq!(two_point_75.to_string(), \"2.8\"); // inherent methods that do not require Frac bounds, some of which can thus be const fixed_no_frac! { $Fixed[$s_fixed]($Inner[$s_inner], $LeEqU, $s_nbits), - $nbytes, $bytes_val, $be_bytes, $le_bytes, + $nbytes, $bytes_val, $rev_bytes_val, $be_bytes, $le_bytes, $UFixed[$s_ufixed], $UInner, $Signedness, $Double, $DoubleInner, $HasDouble } @@ -490,7 +490,7 @@ assert_eq!(two_point_75.to_string(), \"2.8\"); fixed! { "An eight-bit fixed-point unsigned", FixedU8(u8, LeEqU8, "8", "7", "6", "5", "4"), - 1, "0x12", "[0x12]", "[0x12]", + 1, "0x12", "0x12", "[0x12]", "[0x12]", FixedU8, u8, Unsigned, U8, U7, U6, U5, FixedU16, u16, True @@ -498,7 +498,7 @@ fixed! { fixed! { "A 16-bit fixed-point unsigned", FixedU16(u16, LeEqU16, "16", "15", "14", "13", "12"), - 2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]", + 2, "0x1234", "0x3412", "[0x12, 0x34]", "[0x34, 0x12]", FixedU16, u16, Unsigned, U16, U15, U14, U13, FixedU32, u32, True @@ -506,7 +506,7 @@ fixed! { fixed! { "A 32-bit fixed-point unsigned", FixedU32(u32, LeEqU32, "32", "31", "30", "29", "28"), - 4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]", + 4, "0x1234_5678", "0x7856_3412", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]", FixedU32, u32, Unsigned, U32, U31, U30, U29, FixedU64, u64, True @@ -514,7 +514,7 @@ fixed! { fixed! { "A 64-bit fixed-point unsigned", FixedU64(u64, LeEqU64, "64", "63", "62", "61", "60"), - 8, "0x1234_5678_9ABC_DEF0", + 8, "0x1234_5678_9ABC_DEF0", "0xF0DE_BC8A_7856_3412", "[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]", "[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]", FixedU64, u64, Unsigned, @@ -525,6 +525,7 @@ fixed! { "A 128-bit fixed-point unsigned", FixedU128(u128, LeEqU128, "128", "127", "126", "125", "124"), 16, "0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0", + "0xF0DE_BC9A_7856_3412_F0DE_BC9A_7856_3412", "[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, \ 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]", "[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \ @@ -536,7 +537,7 @@ fixed! { fixed! { "An eight-bit fixed-point signed", FixedI8(i8, LeEqU8, "8", "7", "6", "5", "4"), - 1, "0x12", "[0x12]", "[0x12]", + 1, "0x12", "0x12", "[0x12]", "[0x12]", FixedU8, u8, Signed, U7, U6, U5, U4, FixedI16, i16, True @@ -544,7 +545,7 @@ fixed! { fixed! { "A 16-bit fixed-point signed", FixedI16(i16, LeEqU16, "16", "15", "14", "13", "12"), - 2, "0x1234", "[0x12, 0x34]", "[0x34, 0x12]", + 2, "0x1234", "0x3412", "[0x12, 0x34]", "[0x34, 0x12]", FixedU16, u16, Signed, U15, U14, U13, U12, FixedI32, i32, True @@ -552,7 +553,7 @@ fixed! { fixed! { "A 32-bit fixed-point signed", FixedI32(i32, LeEqU32, "32", "31", "30", "29", "28"), - 4, "0x1234_5678", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]", + 4, "0x1234_5678", "0x7856_3412", "[0x12, 0x34, 0x56, 0x78]", "[0x78, 0x56, 0x34, 0x12]", FixedU32, u32, Signed, U31, U30, U29, U28, FixedI64, i64, True @@ -560,7 +561,7 @@ fixed! { fixed! { "A 64-bit fixed-point signed", FixedI64(i64, LeEqU64, "64", "63", "62", "61", "60"), - 8, "0x1234_5678_9ABC_DEF0", + 8, "0x1234_5678_9ABC_DEF0", "0xF0DE_BC8A_7856_3412", "[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]", "[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]", FixedU64, u64, Signed, @@ -571,6 +572,7 @@ fixed! { "A 128-bit fixed-point signed", FixedI128(i128, LeEqU128, "128", "127", "126", "125", "124"), 16, "0x1234_5678_9ABC_DEF0_1234_5678_9ABC_DEF0", + "0xF0DE_BC9A_7856_3412_F0DE_BC9A_7856_3412", "[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, \ 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]", "[0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, \ diff --git a/src/macros_no_frac.rs b/src/macros_no_frac.rs index a47c70e..1b997b4 100644 --- a/src/macros_no_frac.rs +++ b/src/macros_no_frac.rs @@ -16,7 +16,7 @@ macro_rules! fixed_no_frac { ( $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, + $nbytes:expr, $bytes_val:expr, $rev_bytes_val:expr, $be_bytes:expr, $le_bytes:expr, $UFixed:ident[$s_ufixed:expr], $UInner:ty, $Signedness:tt, $Double:ident, $DoubleInner:ty, $HasDouble:tt ) => { @@ -92,6 +92,113 @@ assert_eq!(Fix::from_num(2).to_bits(), 0b10_0000); } } + comment! { + "Converts a fixed-point number from big endian to the target’s endianness. + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +let f = Fix::from_bits(", $bytes_val, "); +if cfg!(target_endian = \"big\") { + assert_eq!(Fix::from_be(f), f); +} else { + assert_eq!(Fix::from_be(f), f.swap_bytes()); +} +``` +"; + #[inline] + pub const fn from_be(f: $Fixed) -> $Fixed { + $Fixed::from_bits(<$Inner>::from_be(f.to_bits())) + } + } + + comment! { + "Converts a fixed-point number from little endian to the target’s endianness. + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +let f = Fix::from_bits(", $bytes_val, "); +if cfg!(target_endian = \"little\") { + assert_eq!(Fix::from_le(f), f); +} else { + assert_eq!(Fix::from_le(f), f.swap_bytes()); +} +``` +"; + #[inline] + pub const fn from_le(f: $Fixed) -> $Fixed { + $Fixed::from_bits(<$Inner>::from_le(f.to_bits())) + } + } + + comment! { + "Converts `self` to big endian from the target’s endianness. + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +let f = Fix::from_bits(", $bytes_val, "); +if cfg!(target_endian = \"big\") { + assert_eq!(f.to_be(), f); +} else { + assert_eq!(f.to_be(), f.swap_bytes()); +} +``` +"; + #[inline] + pub const fn to_be(self) -> $Fixed { + $Fixed::from_bits(self.to_bits().to_be()) + } + } + + comment! { + "Converts `self` to little endian from the target’s endianness. + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +let f = Fix::from_bits(", $bytes_val, "); +if cfg!(target_endian = \"little\") { + assert_eq!(f.to_le(), f); +} else { + assert_eq!(f.to_le(), f.swap_bytes()); +} +``` +"; + #[inline] + pub const fn to_le(self) -> $Fixed { + $Fixed::from_bits(self.to_bits().to_le()) + } + } + + comment! { + "Reverses the byte order of the fixed-point number. + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +let f = Fix::from_bits(", $bytes_val, "); +let rev = Fix::from_bits(", $rev_bytes_val, "); +assert_eq!(f.swap_bytes(), rev); +``` +"; + #[inline] + pub const fn swap_bytes(self) -> $Fixed { + $Fixed::from_bits(self.to_bits().swap_bytes()) + } + } + comment! { "Creates a fixed-point number from its representation as a byte array in big endian. @@ -344,6 +451,25 @@ assert_eq!(f.trailing_zeros(), 5); } } + comment! { + "Reverses the order of the bits of the fixed-point number. + +# Examples + +```rust +use fixed::{types::extra::U4, ", $s_fixed, "}; +type Fix = ", $s_fixed, "; +let bits = ", $bytes_val, "_", $s_inner, "; +let rev_bits = bits.reverse_bits(); +assert_eq!(Fix::from_bits(bits).reverse_bits(), Fix::from_bits(rev_bits)); +``` +"; + #[inline] + pub const fn reverse_bits(self) -> $Fixed { + $Fixed::from_bits(self.to_bits().reverse_bits()) + } + } + comment! { "Shifts to the left by `n` bits, wrapping the truncated bits to the right end.