1use crate::{
2 Error,
3 value::Value,
4 value_inner::{self, NumberInner},
5};
6use core::{
7 fmt::{self, Display, Formatter},
8 ops::{Add, Div, Mul, Rem, Sub},
9};
10
11#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
16#[cfg_attr(not(feature = "float"), derive(Eq, Ord))]
17pub struct Number(NumberInner);
18
19impl Number {
20 #[inline]
21 const fn new(number: NumberInner) -> Self {
22 Self(value_inner::from_number(number))
23 }
24
25 #[inline]
26 const fn to_representation(self) -> NumberInner {
27 value_inner::to_number(self.0)
28 }
29
30 #[inline]
32 pub const fn from_i64(number: i64) -> Self {
33 Self(value_inner::from_i64(number))
34 }
35
36 #[inline]
38 pub const fn to_i64(self) -> i64 {
39 value_inner::to_i64(self.0)
40 }
41
42 #[inline]
44 pub const fn from_f64(number: f64) -> Self {
45 Self(value_inner::from_f64(number))
46 }
47
48 #[inline]
50 pub const fn to_f64(self) -> f64 {
51 value_inner::to_f64(self.0)
52 }
53
54 #[inline]
55 pub(crate) const fn from_raw(raw: u64) -> Self {
56 Self(value_inner::from_raw(raw))
57 }
58
59 #[inline]
60 pub(crate) const fn to_raw(self) -> u64 {
61 value_inner::to_raw(self.0)
62 }
63}
64
65impl Default for Number {
66 #[inline]
67 fn default() -> Self {
68 Self::new(Default::default())
69 }
70}
71
72impl Add for Number {
73 type Output = Self;
74
75 #[inline]
76 fn add(self, other: Self) -> Self::Output {
77 Self::new(self.to_representation() + other.to_representation())
78 }
79}
80
81impl Sub for Number {
82 type Output = Self;
83
84 #[inline]
85 fn sub(self, other: Self) -> Self::Output {
86 Self::new(self.to_representation() - other.to_representation())
87 }
88}
89
90impl Mul for Number {
91 type Output = Self;
92
93 #[inline]
94 fn mul(self, other: Self) -> Self::Output {
95 Self::new(self.to_representation() * other.to_representation())
96 }
97}
98
99impl Div for Number {
100 type Output = Self;
101
102 #[inline]
103 fn div(self, other: Self) -> Self::Output {
104 Self::new(self.to_representation() / other.to_representation())
105 }
106}
107
108impl Rem for Number {
109 type Output = Self;
110
111 #[inline]
112 fn rem(self, other: Self) -> Self::Output {
113 Self::new(self.to_representation() % other.to_representation())
114 }
115}
116
117impl TryFrom<Value> for Number {
118 type Error = Error;
119
120 #[inline]
121 fn try_from(value: Value) -> Result<Self, Self::Error> {
122 value.to_number().ok_or(Error::NumberExpected)
123 }
124}
125
126impl Display for Number {
127 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
128 write!(formatter, "n{}", self.to_representation())
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use alloc::format;
136
137 #[test]
138 fn default() {
139 assert_eq!(Number::default(), Number::from_i64(0));
140 }
141
142 #[test]
143 fn integer() {
144 assert_eq!(Number::default().to_i64(), 0);
145 assert_eq!(Number::from_i64(42).to_i64(), 42);
146 assert_eq!(Number::from_i64(-1).to_i64(), -1);
147 }
148
149 #[test]
150 fn float() {
151 assert_eq!(Number::default().to_f64(), 0.0);
152 assert_eq!(Number::from_f64(1.0).to_f64(), 1.0);
153 assert_eq!(Number::from_f64(42.0).to_f64(), 42.0);
154 assert_eq!(Number::from_f64(-1.0).to_f64(), -1.0);
155 assert_eq!(Number::from_f64(-42.0).to_f64(), -42.0);
156 }
157
158 #[test]
159 fn format() {
160 assert_eq!(format!("{}", Number::from_i64(42)), "n42");
161 assert_eq!(format!("{}", Number::from_i64(-1)), "n-1");
162 }
163
164 #[test]
165 fn add() {
166 assert_eq!(Number::default() + Number::from_i64(1), Number::from_i64(1));
167 assert_eq!(
168 Number::from_i64(1) + Number::from_i64(2),
169 Number::from_i64(3)
170 );
171 }
172
173 #[test]
174 fn subtract() {
175 assert_eq!(
176 Number::default() - Number::from_i64(1),
177 Number::from_i64(-1)
178 );
179 assert_eq!(Number::from_i64(1) - Number::default(), Number::from_i64(1));
180 assert_eq!(
181 Number::from_i64(3) - Number::from_i64(1),
182 Number::from_i64(2)
183 );
184 }
185
186 #[test]
187 fn multiply() {
188 assert_eq!(Number::default() * Number::from_i64(1), Number::default());
189 assert_eq!(
190 Number::from_i64(1) * Number::from_i64(2),
191 Number::from_i64(2)
192 );
193 assert_eq!(
194 Number::from_i64(2) * Number::from_i64(3),
195 Number::from_i64(6)
196 );
197 }
198
199 #[test]
200 fn divide() {
201 assert_eq!(Number::default() / Number::from_i64(1), Number::default());
202 assert_eq!(
203 Number::from_i64(2) / Number::from_i64(1),
204 Number::from_i64(2)
205 );
206 assert_eq!(
207 Number::from_i64(6) / Number::from_i64(2),
208 Number::from_i64(3)
209 );
210 }
211
212 #[test]
213 fn remainder() {
214 assert_eq!(Number::default() % Number::from_i64(1), Number::default());
215 assert_eq!(
216 Number::from_i64(3) % Number::from_i64(2),
217 Number::from_i64(1)
218 );
219 }
220}