value_trait/
node.rs

1use crate::base::{TypedValue, ValueAsScalar};
2
3use super::{ValueType, fmt};
4use std::convert::TryFrom;
5use std::ops::{Index, IndexMut};
6
7#[cfg(feature = "ordered-float")]
8use ordered_float::OrderedFloat;
9
10#[cfg(not(feature = "ordered-float"))]
11use float_cmp::approx_eq;
12
13mod cmp;
14mod from;
15
16/// Static tape node
17#[derive(Debug, Clone, Copy)]
18#[cfg_attr(feature = "ordered-float", derive(Eq))]
19#[cfg_attr(feature = "c-abi", repr(C))]
20#[cfg_attr(feature = "c-abi", derive(abi_stable::StableAbi))]
21
22pub enum StaticNode {
23    /// A signed 64 bit integer.
24    I64(i64),
25    #[cfg(feature = "128bit")]
26    /// A signed 128 bit integer.
27    I128(i128),
28    /// An unsigned 64 bit integer.
29    U64(u64),
30    #[cfg(feature = "128bit")]
31    /// An unsigned 128 bit integer.
32    U128(u128),
33    /// A floating point value
34    #[cfg(not(feature = "ordered-float"))]
35    F64(f64),
36    #[cfg(feature = "ordered-float")]
37    /// A floating point value, as an `OrderedFloat` (not allow for Eq)
38    F64(OrderedFloat<f64>),
39    /// A boolean value
40    Bool(bool),
41    /// The null value
42    Null,
43}
44
45impl Index<&str> for StaticNode {
46    type Output = ();
47    #[inline]
48    #[must_use]
49    fn index(&self, _index: &str) -> &Self::Output {
50        panic!("Not supported")
51    }
52}
53
54impl Index<usize> for StaticNode {
55    type Output = ();
56    #[inline]
57    #[must_use]
58    fn index(&self, _index: usize) -> &Self::Output {
59        panic!("Not supported")
60    }
61}
62
63impl IndexMut<&str> for StaticNode {
64    #[inline]
65    #[must_use]
66    fn index_mut(&mut self, _index: &str) -> &mut Self::Output {
67        panic!("Not supported")
68    }
69}
70
71impl IndexMut<usize> for StaticNode {
72    #[inline]
73    #[must_use]
74    fn index_mut(&mut self, _index: usize) -> &mut Self::Output {
75        panic!("Not supported")
76    }
77}
78
79impl TypedValue for StaticNode {
80    #[cfg(not(feature = "128bit"))]
81    #[inline]
82    #[must_use]
83    fn value_type(&self) -> ValueType {
84        match self {
85            Self::Null => ValueType::Null,
86            Self::Bool(_) => ValueType::Bool,
87            Self::F64(_) => ValueType::F64,
88            Self::I64(_) => ValueType::I64,
89
90            Self::U64(_) => ValueType::U64,
91        }
92    }
93
94    #[cfg(feature = "128bit")]
95    #[inline]
96    #[must_use]
97    fn value_type(&self) -> ValueType {
98        match self {
99            Self::Null => ValueType::Null,
100            Self::Bool(_) => ValueType::Bool,
101            Self::F64(_) => ValueType::F64,
102            Self::I128(_) => ValueType::I128,
103            Self::I64(_) => ValueType::I64,
104            Self::U128(_) => ValueType::U128,
105            Self::U64(_) => ValueType::U64,
106        }
107    }
108}
109
110impl ValueAsScalar for StaticNode {
111    #[inline]
112    #[must_use]
113    fn as_null(&self) -> Option<()> {
114        match self {
115            Self::Null => Some(()),
116            _ => None,
117        }
118    }
119    #[inline]
120    #[must_use]
121    fn as_bool(&self) -> Option<bool> {
122        match self {
123            Self::Bool(b) => Some(*b),
124            _ => None,
125        }
126    }
127
128    #[cfg(not(feature = "128bit"))]
129    #[inline]
130    #[must_use]
131    fn as_i64(&self) -> Option<i64> {
132        match self {
133            Self::I64(i) => Some(*i),
134            Self::U64(i) => i64::try_from(*i).ok(),
135            _ => None,
136        }
137    }
138
139    #[cfg(feature = "128bit")]
140    #[inline]
141    #[must_use]
142    fn as_i64(&self) -> Option<i64> {
143        match self {
144            Self::I64(i) => Some(*i),
145            Self::U64(i) => i64::try_from(*i).ok(),
146            Self::I128(i) => i64::try_from(*i).ok(),
147            Self::U128(i) => i64::try_from(*i).ok(),
148            _ => None,
149        }
150    }
151
152    #[cfg(feature = "128bit")]
153    #[inline]
154    #[must_use]
155    fn as_i128(&self) -> Option<i128> {
156        match self {
157            Self::I128(i) => Some(*i),
158            Self::U128(i) => i128::try_from(*i).ok(),
159            Self::I64(i) => Some(i128::from(*i)),
160            Self::U64(i) => Some(i128::from(*i)),
161            _ => None,
162        }
163    }
164
165    #[cfg(not(feature = "128bit"))]
166    #[inline]
167    #[must_use]
168    fn as_u64(&self) -> Option<u64> {
169        match self {
170            Self::I64(i) => u64::try_from(*i).ok(),
171            Self::U64(i) => Some(*i),
172            _ => None,
173        }
174    }
175
176    #[cfg(feature = "128bit")]
177    #[inline]
178    #[must_use]
179    fn as_u64(&self) -> Option<u64> {
180        match self {
181            Self::I64(i) => u64::try_from(*i).ok(),
182            Self::U64(i) => Some(*i),
183            Self::I128(i) => u64::try_from(*i).ok(),
184            Self::U128(i) => u64::try_from(*i).ok(),
185            _ => None,
186        }
187    }
188    #[cfg(feature = "128bit")]
189    #[inline]
190    #[must_use]
191    fn as_u128(&self) -> Option<u128> {
192        match self {
193            Self::U128(i) => Some(*i),
194            Self::I128(i) => u128::try_from(*i).ok(),
195            Self::I64(i) => u128::try_from(*i).ok(),
196            Self::U64(i) => Some(u128::from(*i)),
197            _ => None,
198        }
199    }
200
201    #[inline]
202    #[must_use]
203    fn as_f64(&self) -> Option<f64> {
204        match self {
205            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
206            Self::F64(i) => Some((*i).into()),
207            _ => None,
208        }
209    }
210
211    #[cfg(not(feature = "128bit"))]
212    #[inline]
213    #[must_use]
214    #[allow(clippy::cast_precision_loss)]
215    fn cast_f64(&self) -> Option<f64> {
216        match self {
217            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
218            Self::F64(i) => Some((*i).into()),
219            Self::I64(i) => Some(*i as f64),
220            Self::U64(i) => Some(*i as f64),
221            _ => None,
222        }
223    }
224
225    #[cfg(feature = "128bit")]
226    #[inline]
227    #[allow(clippy::cast_precision_loss)]
228    fn cast_f64(&self) -> Option<f64> {
229        match self {
230            #[allow(clippy::useless_conversion)] // .into() required by ordered-float
231            Self::F64(i) => Some((*i).into()),
232            Self::I64(i) => Some(*i as f64),
233            Self::U64(i) => Some(*i as f64),
234            Self::I128(i) => Some(*i as f64),
235            Self::U128(i) => Some(*i as f64),
236            _ => None,
237        }
238    }
239
240    #[inline]
241    #[must_use]
242    fn as_str(&self) -> Option<&str> {
243        None
244    }
245}
246
247impl fmt::Display for StaticNode {
248    #[cfg(not(feature = "128bit"))]
249    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250        match self {
251            Self::Null => write!(f, "null"),
252            Self::Bool(b) => write!(f, "{b}"),
253            Self::I64(n) => write!(f, "{n}"),
254            Self::U64(n) => write!(f, "{n}"),
255            #[cfg(not(feature = "ordered-float"))]
256            Self::F64(n) => write!(f, "{n}"),
257            #[cfg(feature = "ordered-float")]
258            Self::F64(n) => write!(f, "{}", n.0),
259        }
260    }
261    #[cfg(feature = "128bit")]
262    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
263        match self {
264            Self::Null => write!(f, "null"),
265            Self::Bool(b) => write!(f, "{b}"),
266            Self::I64(n) => write!(f, "{n}"),
267            Self::U64(n) => write!(f, "{n}"),
268            #[cfg(not(feature = "ordered-float"))]
269            Self::F64(n) => write!(f, "{n}"),
270            #[cfg(feature = "ordered-float")]
271            Self::F64(n) => write!(f, "{}", n.0),
272            Self::I128(n) => write!(f, "{n}"),
273            Self::U128(n) => write!(f, "{n}"),
274        }
275    }
276}
277
278#[allow(clippy::cast_sign_loss, clippy::default_trait_access)]
279impl PartialEq for StaticNode {
280    #[cfg(not(feature = "128bit"))]
281    #[inline]
282    #[must_use]
283    fn eq(&self, other: &Self) -> bool {
284        match (self, other) {
285            (Self::Null, Self::Null) => true,
286            (Self::Bool(v1), Self::Bool(v2)) => v1.eq(v2),
287            #[cfg(not(feature = "ordered-float"))]
288            (Self::F64(v1), Self::F64(v2)) => approx_eq!(f64, *v1, *v2),
289            #[cfg(feature = "ordered-float")]
290            (Self::F64(v1), Self::F64(v2)) => v1.eq(v2),
291            (Self::U64(v1), Self::U64(v2)) => v1.eq(v2),
292            (Self::I64(v1), Self::I64(v2)) => v1.eq(v2),
293            (Self::U64(v1), Self::I64(v2)) if *v2 >= 0 => (*v2 as u64).eq(v1),
294            (Self::I64(v1), Self::U64(v2)) if *v1 >= 0 => (*v1 as u64).eq(v2),
295            _ => false,
296        }
297    }
298
299    #[cfg(feature = "128bit")]
300    #[inline]
301    #[must_use]
302    fn eq(&self, other: &Self) -> bool {
303        match (self, other) {
304            (Self::Null, Self::Null) => true,
305            (Self::Bool(v1), Self::Bool(v2)) => v1.eq(v2),
306            #[cfg(not(feature = "ordered-float"))]
307            (Self::F64(v1), Self::F64(v2)) => approx_eq!(f64, *v1, *v2),
308            #[cfg(feature = "ordered-float")]
309            (Self::F64(v1), Self::F64(v2)) => v1.eq(v2),
310            (Self::U64(v1), Self::U64(v2)) => v1.eq(v2),
311            (Self::U128(v1), Self::U128(v2)) => v1.eq(v2),
312            (Self::I64(v1), Self::I64(v2)) => v1.eq(v2),
313            (Self::I128(v1), Self::I128(v2)) => v1.eq(v2),
314
315            (Self::U64(v1), Self::I64(v2)) if *v2 >= 0 => (*v2 as u64).eq(v1),
316            (Self::U64(v1), Self::I128(v2)) if *v2 >= 0 => (*v2 as u128).eq(&u128::from(*v1)),
317            (Self::U64(v1), Self::U128(v2)) => v2.eq(&u128::from(*v1)),
318
319            (Self::I64(v1), Self::U64(v2)) if *v1 >= 0 => (*v1 as u64).eq(v2),
320            (Self::I64(v1), Self::I128(v2)) => (*v2).eq(&i128::from(*v1)),
321            (Self::I64(v1), Self::U128(v2)) if *v1 >= 0 => v2.eq(&(*v1 as u128)),
322
323            (Self::U128(v1), Self::I128(v2)) if *v2 >= 0 => (*v2 as u128).eq(v1),
324            (Self::U128(v1), Self::U64(v2)) => v1.eq(&u128::from(*v2)),
325            (Self::U128(v1), Self::I64(v2)) if *v2 >= 0 => v1.eq(&(*v2 as u128)),
326
327            (Self::I128(v1), Self::U128(v2)) if *v1 >= 0 => (*v1 as u128).eq(v2),
328            (Self::I128(v1), Self::U64(v2)) => v1.eq(&i128::from(*v2)),
329            (Self::I128(v1), Self::I64(v2)) => v1.eq(&i128::from(*v2)),
330            _ => false,
331        }
332    }
333}
334
335impl Default for StaticNode {
336    #[must_use]
337    fn default() -> Self {
338        Self::Null
339    }
340}