spo_rhai/types/
float.rs

1#![cfg(not(feature = "no_float"))]
2
3#[cfg(feature = "no_std")]
4use std::prelude::v1::*;
5use std::{
6    fmt,
7    hash::{Hash, Hasher},
8    ops::{Deref, DerefMut},
9    str::FromStr,
10};
11
12use num_traits::float::FloatCore as Float;
13
14/// _(internals)_ A type that wraps a floating-point number and implements [`Hash`].
15/// Exported under the `internals` feature only.
16///
17/// Not available under `no_float`.
18#[derive(Clone, Copy, Eq, PartialEq, PartialOrd)]
19#[must_use]
20pub struct FloatWrapper<F>(F);
21
22impl Hash for FloatWrapper<crate::FLOAT> {
23    #[inline]
24    fn hash<H: Hasher>(&self, state: &mut H) {
25        self.0.to_ne_bytes().hash(state);
26    }
27}
28
29impl<F: Float> AsRef<F> for FloatWrapper<F> {
30    #[inline(always)]
31    #[must_use]
32    fn as_ref(&self) -> &F {
33        &self.0
34    }
35}
36
37impl<F: Float> AsMut<F> for FloatWrapper<F> {
38    #[inline(always)]
39    #[must_use]
40    fn as_mut(&mut self) -> &mut F {
41        &mut self.0
42    }
43}
44
45impl<F: Float> Deref for FloatWrapper<F> {
46    type Target = F;
47
48    #[inline(always)]
49    fn deref(&self) -> &Self::Target {
50        &self.0
51    }
52}
53
54impl<F: Float> DerefMut for FloatWrapper<F> {
55    #[inline(always)]
56    fn deref_mut(&mut self) -> &mut Self::Target {
57        &mut self.0
58    }
59}
60
61impl<F: Float + fmt::Debug> fmt::Debug for FloatWrapper<F> {
62    #[cold]
63    #[inline(never)]
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        fmt::Debug::fmt(&self.0, f)
66    }
67}
68
69impl<F: Float + fmt::Display + fmt::LowerExp + From<f32>> fmt::Display for FloatWrapper<F> {
70    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71        let abs = self.0.abs();
72        if abs.is_zero() {
73            f.write_str("0.0")
74        } else if abs > Self::MAX_NATURAL_FLOAT_FOR_DISPLAY.into()
75            || abs < Self::MIN_NATURAL_FLOAT_FOR_DISPLAY.into()
76        {
77            write!(f, "{:e}", self.0)
78        } else {
79            fmt::Display::fmt(&self.0, f)?;
80            if abs.fract().is_zero() {
81                f.write_str(".0")?;
82            }
83            Ok(())
84        }
85    }
86}
87
88impl<F: Float> From<F> for FloatWrapper<F> {
89    #[inline(always)]
90    fn from(value: F) -> Self {
91        Self::new(value)
92    }
93}
94
95impl<F: Float + FromStr> FromStr for FloatWrapper<F> {
96    type Err = <F as FromStr>::Err;
97
98    #[inline]
99    fn from_str(s: &str) -> Result<Self, Self::Err> {
100        F::from_str(s).map(Into::into)
101    }
102}
103
104impl<F: Float> FloatWrapper<F> {
105    /// Maximum floating-point number for natural display before switching to scientific notation.
106    pub const MAX_NATURAL_FLOAT_FOR_DISPLAY: f32 = 10_000_000_000_000.0;
107
108    /// Minimum floating-point number for natural display before switching to scientific notation.
109    pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.000_000_000_000_1;
110
111    /// Create a new [`FloatWrapper`].
112    #[inline(always)]
113    pub const fn new(value: F) -> Self {
114        Self(value)
115    }
116}