drasi_core/evaluation/variable_value/
float.rs

1// Copyright 2024 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::evaluation::variable_value::integer::Integer;
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, Default)]
22pub struct Float {
23    value: f64,
24}
25
26impl PartialEq for Float {
27    fn eq(&self, other: &Self) -> bool {
28        let (a, b) = (self.value, other.value);
29        a == b
30    }
31}
32
33impl PartialEq<f64> for Float {
34    fn eq(&self, other: &f64) -> bool {
35        let (a, b) = (self.value, *other);
36        a == b
37    }
38}
39
40impl PartialEq<Integer> for Float {
41    fn eq(&self, other: &Integer) -> bool {
42        match (self.value, other.as_i64()) {
43            (a, Some(b)) => a == b as f64,
44            _ => false,
45        }
46    }
47}
48
49impl Eq for Float {}
50
51impl Hash for Float {
52    fn hash<H: Hasher>(&self, h: &mut H) {
53        match self.value {
54            f if f == 0.0f64 => {
55                // There are 2 zero representations, +0 and -0, which
56                // compare equal but have different bits. We use the +0 hash
57                // for both so that hash(+0) == hash(-0).
58                0.0f64.to_bits().hash(h);
59            }
60            f => {
61                f.to_bits().hash(h);
62            }
63        }
64    }
65}
66
67impl Float {
68    #[inline]
69    pub fn is_f64(&self) -> bool {
70        self.value.is_finite()
71    }
72
73    pub(crate) fn as_f64(&self) -> Option<f64> {
74        match self.value {
75            n if n.is_finite() => Some(n),
76            _ => None,
77        }
78    }
79
80    pub(crate) fn as_f32(&self) -> Option<f32> {
81        match self.value {
82            n if n.is_finite() => Some(n as f32),
83            _ => None,
84        }
85    }
86
87    #[inline]
88    pub fn from_f64(f: f64) -> Option<Float> {
89        if f.is_finite() {
90            Some(Float { value: f })
91        } else {
92            None
93        }
94    }
95
96    #[inline]
97    pub(crate) fn from_f32(f: f32) -> Option<Float> {
98        if f.is_finite() {
99            Some(Float { value: f as f64 })
100        } else {
101            None
102        }
103    }
104}
105
106impl From<Float> for Number {
107    fn from(val: Float) -> Self {
108        Number::from_f64(val.value).expect("a finite float")
109    }
110}
111
112impl Debug for Float {
113    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
114        write!(formatter, "Float({})", self)
115    }
116}
117
118impl Display for Float {
119    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
120        {
121            let value = &self.value;
122            formatter.write_str(&value.to_string())
123        }
124    }
125}
126
127impl<'de> Deserialize<'de> for Float {
128    #[inline]
129    fn deserialize<D>(deserializer: D) -> Result<Float, D::Error>
130    where
131        D: Deserializer<'de>,
132    {
133        struct NumberVisitor;
134
135        impl<'de> Visitor<'de> for NumberVisitor {
136            type Value = Float;
137
138            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
139                formatter.write_str("a JSON number")
140            }
141
142            #[inline]
143            fn visit_f64<E>(self, value: f64) -> Result<Float, E>
144            where
145                E: de::Error,
146            {
147                Ok(Float::from(value))
148            }
149
150            #[inline]
151            fn visit_f32<E>(self, value: f32) -> Result<Float, E>
152            where
153                E: de::Error,
154            {
155                Ok(Float::from(value))
156            }
157        }
158
159        deserializer.deserialize_any(NumberVisitor)
160    }
161}
162
163macro_rules! impl_from_float {
164    (
165        $($ty:ty),*
166    ) => {
167        $(
168            impl From<$ty> for Float {
169                #[inline]
170                fn from(i: $ty) -> Self {
171                    let n = {
172                        {
173                            i as f64
174                        }
175                    };
176                    Float { value: n }
177                }
178            }
179        )*
180    };
181}
182
183impl_from_float!(f32, f64, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);