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