Skip to main content

scratch_test_value/conversions/
to_float.rs

1use crate::{ARc, QuirkSink, SNumber, SValue};
2
3/// Generated by [`SValue::q_as_float`]
4pub enum SValueToFloatQ {
5    /// [`true`] will be treated as (float) 1.0, [`false`] as (float) 0.0
6    BoolNotANumber(bool),
7    /// The text is converted to the (float) number 0.0
8    TextNotANumber(ARc<str>),
9    /// The stored integer has lost precision after converting it to a float
10    IntToFloatNotLossless,
11}
12
13/// Generated by [`SNumber::q_as_float`]
14pub enum SNumberToFloatQ {
15    /// The stored integer has lost precision after converting it to a float
16    IntToFloatNotLossless,
17}
18
19impl SValue {
20    pub fn q_as_float<Q>(&self, sink: &mut Q) -> f64
21    where
22        Q: QuirkSink<SValueToFloatQ>,
23    {
24        match self {
25            Self::Bool(b) => {
26                sink.put(SValueToFloatQ::BoolNotANumber(*b));
27                if *b { 1.0 } else { 0.0 }
28            }
29            Self::Text(t) => {
30                if let Ok(f) = t.parse() {
31                    f
32                } else {
33                    sink.put(SValueToFloatQ::TextNotANumber(t.clone()));
34                    0.0
35                }
36            }
37            Self::Int(i1) => {
38                let f: f64 = (*i1) as f64;
39                let i2 = f as i64;
40                if *i1 != i2 {
41                    sink.put(SValueToFloatQ::IntToFloatNotLossless);
42                }
43                f
44            }
45            Self::Float(f) => *f,
46        }
47    }
48}
49impl SNumber {
50    pub fn q_as_float<Q>(&self, sink: &mut Q) -> f64
51    where
52        Q: QuirkSink<SNumberToFloatQ>,
53    {
54        match self {
55            Self::Int(i1) => {
56                let f: f64 = (*i1) as f64;
57                let i2 = f as i64;
58                if *i1 != i2 {
59                    sink.put(SNumberToFloatQ::IntToFloatNotLossless);
60                }
61                f
62            }
63            Self::Float(f) => *f,
64        }
65    }
66    /// internal convenience method that transforms the [`f64`] from
67    /// [`Self::q_as_float`] to [`0`] if it was [`f64::NAN`]
68    /// as many Scratch blocks treat [`f64::NAN`] as zero.
69    pub(crate) fn q_as_float_nan_is_zero<Q>(&self, sink: &mut Q) -> f64
70    where
71        Q: QuirkSink<SNumberToFloatQ>,
72    {
73        let f = self.q_as_float(sink);
74        if f.is_nan() { 0.0 } else { f }
75    }
76}