1use crate::{derive_display, NativeCast, Portable};
2use core::{
3 cmp::{Ordering, PartialOrd},
4 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
5};
6use flatty_base::{
7 error::Error,
8 traits::{Flat, FlatValidate},
9};
10use num_traits::{Bounded, FromPrimitive, Num, NumCast, One, ToPrimitive, Zero};
11
12#[repr(C)]
18#[derive(Clone, Copy, PartialEq, Eq, Hash)]
19pub struct Float<const BE: bool, const N: usize> {
20 bytes: [u8; N],
21}
22
23impl<const BE: bool, const N: usize> Default for Float<BE, N> {
24 fn default() -> Self {
25 Self { bytes: [0; N] }
26 }
27}
28
29impl<const BE: bool, const N: usize> Float<BE, N> {
30 pub fn from_bytes(bytes: [u8; N]) -> Self {
31 Self { bytes }
32 }
33 pub fn to_bytes(self) -> [u8; N] {
34 self.bytes
35 }
36}
37
38unsafe impl<const BE: bool, const N: usize> FlatValidate for Float<BE, N> {
39 unsafe fn validate_unchecked(_: &[u8]) -> Result<(), Error> {
40 Ok(())
41 }
42}
43
44unsafe impl<const BE: bool, const N: usize> Flat for Float<BE, N> {}
45
46unsafe impl<const BE: bool, const N: usize> Portable for Float<BE, N> {}
47
48macro_rules! derive_float {
49 ($self:ty, $native:ty, $from_bytes:ident, $to_bytes:ident$(,)?) => {
50 impl NativeCast for $self {
51 type Native = $native;
52 fn from_native(n: $native) -> Self {
53 Float::from_bytes(n.$to_bytes())
54 }
55 fn to_native(&self) -> Self::Native {
56 <$native>::$from_bytes(self.to_bytes())
57 }
58 }
59
60 impl From<$native> for $self {
61 fn from(n: $native) -> Self {
62 Self::from_native(n)
63 }
64 }
65 impl From<$self> for $native {
66 fn from(s: $self) -> Self {
67 s.to_native()
68 }
69 }
70
71 impl NumCast for $self {
72 fn from<T: ToPrimitive>(n: T) -> Option<Self> {
73 Some(Self::from_native(<$native as NumCast>::from::<T>(n)?))
74 }
75 }
76 impl ToPrimitive for $self {
77 fn to_u64(&self) -> Option<u64> {
78 self.to_native().to_u64()
79 }
80 fn to_i64(&self) -> Option<i64> {
81 self.to_native().to_i64()
82 }
83 }
84 impl FromPrimitive for $self {
85 fn from_u64(n: u64) -> Option<Self> {
86 Some(Float::from_native(<$native>::from_u64(n)?))
87 }
88 fn from_i64(n: i64) -> Option<Self> {
89 Some(Float::from_native(<$native>::from_i64(n)?))
90 }
91 }
92
93 impl Num for $self {
94 type FromStrRadixErr = <$native as Num>::FromStrRadixErr;
95 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
96 Ok(Self::from_native(<$native as Num>::from_str_radix(str, radix)?))
97 }
98 }
99
100 impl Bounded for $self {
101 fn min_value() -> Self {
102 Self::from_native(<$native>::MIN)
103 }
104 fn max_value() -> Self {
105 Self::from_native(<$native>::MAX)
106 }
107 }
108
109 impl One for $self {
110 fn one() -> Self {
111 Self::from_native(<$native>::one())
112 }
113 }
114 impl Zero for $self {
115 fn zero() -> Self {
116 Self::from_native(<$native>::zero())
117 }
118 fn is_zero(&self) -> bool {
119 self.to_native().is_zero()
120 }
121 }
122
123 impl Add for $self {
124 type Output = Self;
125 fn add(self, rhs: Self) -> Self {
126 Self::from_native(self.to_native() + rhs.to_native())
127 }
128 }
129 impl Sub for $self {
130 type Output = Self;
131 fn sub(self, rhs: Self) -> Self {
132 Self::from_native(self.to_native() - rhs.to_native())
133 }
134 }
135 impl Mul for $self {
136 type Output = Self;
137 fn mul(self, rhs: Self) -> Self {
138 Self::from_native(self.to_native() * rhs.to_native())
139 }
140 }
141 impl Div for $self {
142 type Output = Self;
143 fn div(self, rhs: Self) -> Self {
144 Self::from_native(self.to_native() / rhs.to_native())
145 }
146 }
147 impl Rem for $self {
148 type Output = Self;
149 fn rem(self, rhs: Self) -> Self {
150 Self::from_native(self.to_native() % rhs.to_native())
151 }
152 }
153 impl Neg for $self {
154 type Output = Self;
155 fn neg(self) -> Self::Output {
156 Self::from_native(-self.to_native())
157 }
158 }
159
160 impl PartialOrd for $self {
161 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
162 self.to_native().partial_cmp(&other.to_native())
163 }
164 }
165
166 impl AddAssign for $self {
167 fn add_assign(&mut self, rhs: Self) {
168 *self = self.add(rhs);
169 }
170 }
171 impl SubAssign for $self {
172 fn sub_assign(&mut self, rhs: Self) {
173 *self = self.sub(rhs);
174 }
175 }
176 impl MulAssign for $self {
177 fn mul_assign(&mut self, rhs: Self) {
178 *self = self.mul(rhs);
179 }
180 }
181 impl DivAssign for $self {
182 fn div_assign(&mut self, rhs: Self) {
183 *self = self.div(rhs);
184 }
185 }
186 impl RemAssign for $self {
187 fn rem_assign(&mut self, rhs: Self) {
188 *self = self.rem(rhs);
189 }
190 }
191
192 derive_display!($self, $native);
193 };
194}
195
196macro_rules! derive_le_float {
197 ($self:ty, $native:ty $(,)?) => {
198 derive_float!($self, $native, from_le_bytes, to_le_bytes);
199 };
200}
201
202macro_rules! derive_be_float {
203 ($self:ty, $native:ty $(,)?) => {
204 derive_float!($self, $native, from_be_bytes, to_be_bytes);
205 };
206}
207
208derive_le_float!(Float<false, 4>, f32);
209derive_le_float!(Float<false, 8>, f64);
210
211derive_be_float!(Float<true, 4>, f32);
212derive_be_float!(Float<true, 8>, f64);
213
214pub mod le {
215 use super::Float;
216
217 pub type F32 = Float<false, 4>;
218 pub type F64 = Float<false, 8>;
219}
220
221pub mod be {
222 use super::Float;
223
224 pub type F32 = Float<true, 4>;
225 pub type F64 = Float<true, 8>;
226}