lilliput_float/
be_bytes.rs1use crate::floats::{F16, F24, F32, F40, F48, F56, F64, F8};
2
3pub trait FpFromBeBytes {
4 type Bytes;
5
6 fn from_be_bytes(be_bytes: Self::Bytes) -> Self;
7}
8
9macro_rules! impl_float_from_be_bytes {
10 ($t:ty => bytes: [u8; $bytes:expr], bits: $bits:ty) => {
11 impl FpFromBeBytes for $t {
12 type Bytes = [u8; $bytes];
13
14 fn from_be_bytes(be_bytes: Self::Bytes) -> Self {
15 const PADDED_BYTES: usize = (<$bits>::BITS / u8::BITS) as usize;
16 const PADDING: usize = (PADDED_BYTES - $bytes) as usize;
17 let zeroed_bits: $bits = 0b0;
18 let mut padded_be_bytes: [u8; PADDED_BYTES] = zeroed_bits.to_be_bytes();
19 padded_be_bytes[PADDING..].copy_from_slice(&be_bytes);
20 Self(<$bits>::from_be_bytes(padded_be_bytes))
21 }
22 }
23 };
24}
25
26impl_float_from_be_bytes!(F8 => bytes: [u8; 1], bits: u8);
27impl_float_from_be_bytes!(F16 => bytes: [u8; 2], bits: u16);
28impl_float_from_be_bytes!(F24 => bytes: [u8; 3], bits: u32);
29impl_float_from_be_bytes!(F32 => bytes: [u8; 4], bits: u32);
30impl_float_from_be_bytes!(F40 => bytes: [u8; 5], bits: u64);
31impl_float_from_be_bytes!(F48 => bytes: [u8; 6], bits: u64);
32impl_float_from_be_bytes!(F56 => bytes: [u8; 7], bits: u64);
33impl_float_from_be_bytes!(F64 => bytes: [u8; 8], bits: u64);
34
35pub trait FpToBeBytes {
36 type Bytes;
37
38 fn to_be_bytes(self) -> Self::Bytes;
39}
40
41macro_rules! impl_float_to_be_bytes {
42 ($t:ty => bytes: [u8; $bytes:expr], bits: $bits:ty) => {
43 impl FpToBeBytes for $t {
44 type Bytes = [u8; $bytes];
45
46 fn to_be_bytes(self) -> Self::Bytes {
47 const PADDED_BYTES: usize = (<$bits>::BITS / u8::BITS) as usize;
48 const PADDING: usize = (PADDED_BYTES - $bytes) as usize;
49 let padded_be_bytes: [u8; PADDED_BYTES] = self.0.to_be_bytes();
50 let mut be_bytes: [u8; $bytes] = [0b0; $bytes];
51 be_bytes.copy_from_slice(&padded_be_bytes[PADDING..]);
52 be_bytes
53 }
54 }
55 };
56}
57
58impl_float_to_be_bytes!(F8 => bytes: [u8; 1], bits: u8);
59impl_float_to_be_bytes!(F16 => bytes: [u8; 2], bits: u16);
60impl_float_to_be_bytes!(F24 => bytes: [u8; 3], bits: u32);
61impl_float_to_be_bytes!(F32 => bytes: [u8; 4], bits: u32);
62impl_float_to_be_bytes!(F40 => bytes: [u8; 5], bits: u64);
63impl_float_to_be_bytes!(F48 => bytes: [u8; 6], bits: u64);
64impl_float_to_be_bytes!(F56 => bytes: [u8; 7], bits: u64);
65impl_float_to_be_bytes!(F64 => bytes: [u8; 8], bits: u64);
66
67#[cfg(test)]
68mod tests {
69 use proptest::prelude::*;
70
71 use super::*;
72
73 proptest! {
74 #[test]
75 fn f8_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 1]>::arbitrary()) {
76 let float = F8::from_be_bytes(be_bytes_before);
77 let be_bytes_after = float.to_be_bytes();
78 prop_assert_eq!(be_bytes_before, be_bytes_after);
79 }
80
81 #[test]
82 fn f16_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 2]>::arbitrary()) {
83 let float = F16::from_be_bytes(be_bytes_before);
84 let be_bytes_after = float.to_be_bytes();
85 prop_assert_eq!(be_bytes_before, be_bytes_after);
86 }
87
88 #[test]
89 fn f24_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 3]>::arbitrary()) {
90 let float = F24::from_be_bytes(be_bytes_before);
91 let be_bytes_after = float.to_be_bytes();
92 prop_assert_eq!(be_bytes_before, be_bytes_after);
93 }
94
95 #[test]
96 fn f32_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 4]>::arbitrary()) {
97 let float = F32::from_be_bytes(be_bytes_before);
98 let be_bytes_after = float.to_be_bytes();
99 prop_assert_eq!(be_bytes_before, be_bytes_after);
100 }
101
102 #[test]
103 fn f40_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 5]>::arbitrary()) {
104 let float = F40::from_be_bytes(be_bytes_before);
105 let be_bytes_after = float.to_be_bytes();
106 prop_assert_eq!(be_bytes_before, be_bytes_after);
107 }
108
109 #[test]
110 fn f48_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 6]>::arbitrary()) {
111 let float = F48::from_be_bytes(be_bytes_before);
112 let be_bytes_after = float.to_be_bytes();
113 prop_assert_eq!(be_bytes_before, be_bytes_after);
114 }
115
116 #[test]
117 fn f56_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 7]>::arbitrary()) {
118 let float = F56::from_be_bytes(be_bytes_before);
119 let be_bytes_after = float.to_be_bytes();
120 prop_assert_eq!(be_bytes_before, be_bytes_after);
121 }
122
123 #[test]
124 fn f64_from_to_be_bytes_roundtrip(be_bytes_before in <[u8; 8]>::arbitrary()) {
125 let float = F64::from_be_bytes(be_bytes_before);
126 let be_bytes_after = float.to_be_bytes();
127 prop_assert_eq!(be_bytes_before, be_bytes_after);
128 }
129 }
130}