Skip to main content

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