scratch_test_value/conversions/
to_number.rs1use crate::{ARc, QuirkSink, SNumber, SValue};
2
3pub enum SValueToNumberQ {
5 BoolNotANumber(bool),
7 TextNotANumber(ARc<str>),
9}
10
11impl SValue {
12 pub fn q_as_number_permissive_bool_text<Q>(&self, sink: &mut Q) -> SNumber
13 where
14 Q: QuirkSink<SValueToNumberQ>,
15 {
16 match self {
17 Self::Bool(b) => {
18 sink.put(SValueToNumberQ::BoolNotANumber(*b));
19 if *b { SNumber::Int(1) } else { SNumber::Int(0) }
20 }
21 Self::Text(t) => {
22 if t.as_ref() == "true" {
23 sink.put(SValueToNumberQ::BoolNotANumber(true));
24 SNumber::Int(1)
25 } else if t.as_ref() == "false" {
26 sink.put(SValueToNumberQ::BoolNotANumber(false));
27 SNumber::Int(0)
28 } else if let Ok(i) = t.parse() {
29 SNumber::Int(i)
30 } else if let Ok(f) = t.parse() {
31 SNumber::Float(f)
32 } else {
33 sink.put(SValueToNumberQ::TextNotANumber(t.clone()));
34 SNumber::Int(0)
35 }
36 }
37 Self::Int(i) => SNumber::Int(*i),
38 Self::Float(f) => SNumber::Float(*f),
39 }
40 }
41 pub fn q_as_number<Q>(&self, sink: &mut Q) -> SNumber
42 where
43 Q: QuirkSink<SValueToNumberQ>,
44 {
45 self.q_as_number_strict_bool_text(sink)
46 }
47
48 pub fn q_as_number_strict_bool_text<Q>(&self, sink: &mut Q) -> SNumber
56 where
57 Q: QuirkSink<SValueToNumberQ>,
58 {
59 match self {
60 Self::Bool(b) => {
61 sink.put(SValueToNumberQ::BoolNotANumber(*b));
62 if *b { SNumber::Int(1) } else { SNumber::Int(0) }
63 }
64 Self::Text(t) => {
65 if let Ok(i) = t.parse() {
66 SNumber::Int(i)
67 } else if let Ok(f) = t.parse() {
68 SNumber::Float(f)
69 } else {
70 sink.put(SValueToNumberQ::TextNotANumber(t.clone()));
71 SNumber::Int(0)
72 }
73 }
74 Self::Int(i) => SNumber::Int(*i),
75 Self::Float(f) => SNumber::Float(*f),
76 }
77 }
78}
79
80impl SNumber {
81 pub fn int_or_border<Q>(&self, sink: &mut Q) -> i64
82 where
83 Q: QuirkSink<NumberTooBigForIntQ>,
84 {
85 match self {
86 Self::Int(i) => *i,
87 Self::Float(f) => {
88 if !((f.is_sign_positive() && *f <= (i64::MAX as f64))
89 || (f.is_sign_negative() && *f >= (i64::MIN as f64)))
90 {
91 sink.put(NumberTooBigForIntQ(*f));
92 }
93 *f as i64
94 }
95 }
96 }
97}
98
99#[allow(unused)]
100pub struct NumberTooBigForIntQ(f64);