drasi_core/evaluation/variable_value/
integer.rs1use crate::evaluation::variable_value::float::Float;
16use core::fmt::{self, Debug, Display};
17use core::hash::{Hash, Hasher};
18use serde::de::{self, Deserialize, Deserializer, Visitor};
19use serde_json::Number;
20
21#[derive(Clone, PartialEq, Hash)]
22pub struct Integer {
23 n: N,
24}
25
26#[derive(Copy, Clone)]
27enum N {
28 PosInt(u64), NegInt(i64),
30}
31
32impl PartialEq for N {
33 fn eq(&self, other: &Self) -> bool {
34 match (self, other) {
35 (N::PosInt(a), N::PosInt(b)) => a == b,
36 (N::NegInt(a), N::NegInt(b)) => a == b,
37 _ => false,
38 }
39 }
40}
41
42impl PartialEq<Float> for N {
43 fn eq(&self, other: &Float) -> bool {
44 match (self, other.as_f64()) {
45 (N::PosInt(a), Some(b)) => *a as f64 == b,
46 (N::NegInt(a), Some(b)) => *a as f64 == b,
47 _ => false,
48 }
49 }
50}
51
52impl Hash for N {
53 fn hash<H: Hasher>(&self, h: &mut H) {
54 match *self {
55 N::PosInt(i) => i.hash(h),
56 N::NegInt(i) => i.hash(h),
57 }
58 }
59}
60
61impl Integer {
62 #[inline]
63 pub fn is_i64(&self) -> bool {
64 match self.n {
65 N::PosInt(v) => v <= i64::MAX as u64,
66 N::NegInt(_) => true,
67 }
68 }
69
70 #[inline]
71 pub fn is_u64(&self) -> bool {
72 match self.n {
73 N::PosInt(_) => true,
74 N::NegInt(_) => false,
75 }
76 }
77
78 #[inline]
79 pub fn as_i64(&self) -> Option<i64> {
80 match self.n {
81 N::PosInt(n) => {
82 if n <= i64::MAX as u64 {
83 Some(n as i64)
84 } else {
85 None
86 }
87 }
88 N::NegInt(n) => Some(n),
89 }
90 }
91
92 #[inline]
93 pub fn as_u64(&self) -> Option<u64> {
94 match self.n {
95 N::PosInt(n) => Some(n),
96 _ => None,
97 }
98 }
99}
100
101impl From<Integer> for Number {
102 fn from(val: Integer) -> Self {
103 match val.n {
104 N::PosInt(u) => Number::from(u),
105 N::NegInt(i) => Number::from(i),
106 }
107 }
108}
109
110impl Eq for Integer {}
111
112impl Display for Integer {
113 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
114 match self.n {
115 N::PosInt(u) => formatter.write_str(itoa::Buffer::new().format(u)),
116 N::NegInt(i) => formatter.write_str(itoa::Buffer::new().format(i)),
117 }
118 }
119}
120
121impl Debug for Integer {
122 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
123 write!(formatter, "Integer({})", self)
124 }
125}
126
127macro_rules! impl_from_unsigned {
128 (
129 $($ty:ty),*
130 ) => {
131 $(
132 impl From<$ty> for Integer {
133 #[inline]
134 fn from(u: $ty) -> Self {
135 let n = {
136 { N::PosInt(u as u64) }
137 };
138 Integer { n }
139 }
140 }
141 )*
142 };
143}
144
145macro_rules! impl_from_signed {
146 (
147 $($ty:ty),*
148 ) => {
149 $(
150 impl From<$ty> for Integer {
151 #[inline]
152 fn from(i: $ty) -> Self {
153 let n = {
154 {
155 if i < 0 {
156 N::NegInt(i as i64)
157 } else {
158 N::PosInt(i as u64)
159 }
160 }
161 };
162 Integer { n }
163 }
164 }
165 )*
166 };
167}
168
169macro_rules! impl_from_float {
170 ($ty:ty) => {
171 impl From<$ty> for Integer {
172 fn from(n: $ty) -> Self {
173 let n = {
174 if n.fract() == 0.0 {
175 N::PosInt(n as u64).into()
176 } else {
177 panic!("Invalid conversion: Cannot convert {} to Integer", n);
178 }
179 };
180 Integer { n }
181 }
182 }
183 };
184}
185
186impl_from_unsigned!(u8, u16, u32, u64, usize);
187impl_from_signed!(i8, i16, i32, i64, isize);
188impl_from_float!(f32);
189impl_from_float!(f64);
190
191impl PartialEq<Float> for Integer {
192 fn eq(&self, other: &Float) -> bool {
193 match (self.n, other.as_f64()) {
194 (N::PosInt(a), Some(b)) => a as f64 == b,
195 (N::NegInt(a), Some(b)) => a as f64 == b,
196 _ => false,
197 }
198 }
199}
200
201impl<'de> Deserialize<'de> for Integer {
202 #[inline]
203 fn deserialize<D>(deserializer: D) -> Result<Integer, D::Error>
204 where
205 D: Deserializer<'de>,
206 {
207 struct NumberVisitor;
208
209 impl<'de> Visitor<'de> for NumberVisitor {
210 type Value = Integer;
211
212 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
213 formatter.write_str("a JSON number")
214 }
215
216 #[inline]
217 fn visit_i64<E>(self, value: i64) -> Result<Integer, E> {
218 Ok(value.into())
219 }
220
221 #[inline]
222 fn visit_u64<E>(self, value: u64) -> Result<Integer, E> {
223 Ok(value.into())
224 }
225
226 #[inline]
227 fn visit_f64<E>(self, value: f64) -> Result<Integer, E>
228 where
229 E: de::Error,
230 {
231 Ok(Integer::from(value))
232 }
233 }
234
235 deserializer.deserialize_any(NumberVisitor)
236 }
237}