Skip to main content

logics_rs/
lib.rs

1use std::collections::HashMap;
2
3#[derive(Debug)]
4enum Value {
5    None,
6    Bool(bool),
7    Int(i64),
8    Float(f64),
9    String(String),
10    List(Vec<Value>),
11    Dict(HashMap<Value, Value>),
12}
13
14impl Value {
15    fn to_bool(&self) -> bool {
16        match self {
17            Self::None => false,
18            Self::Bool(b) => *b,
19            Self::Int(i) => *i != 0,
20            Self::Float(f) => *f != 0.0,
21            Self::String(s) => !s.is_empty(),
22            Self::List(l) => !l.is_empty(),
23            Self::Dict(d) => !d.is_empty(),
24        }
25    }
26
27    fn to_i64(&self) -> i64 {
28        match self {
29            Self::None => 0,
30            Self::Bool(b) => {
31                if *b {
32                    1
33                } else {
34                    0
35                }
36            }
37            Self::Int(i) => *i,
38            Self::Float(f) => *f as i64,
39            Self::String(s) => {
40                if let Ok(i) = s.parse::<i64>() {
41                    i
42                } else {
43                    0
44                }
45            }
46            Self::List(l) => todo!(),
47            Self::Dict(d) => todo!(),
48        }
49    }
50
51    fn to_f64(&self) -> f64 {
52        match self {
53            Self::None => 0.0,
54            Self::Bool(b) => {
55                if *b {
56                    1.0
57                } else {
58                    0.0
59                }
60            }
61            Self::Int(i) => *i as f64,
62            Self::Float(f) => *f,
63            Self::String(s) => {
64                if let Ok(f) = s.parse::<f64>() {
65                    f
66                } else {
67                    0.0
68                }
69            }
70            Self::List(l) => todo!(),
71            Self::Dict(d) => todo!(),
72        }
73    }
74
75    fn to_string(&self) -> String {
76        match self {
77            Self::String(s) => s.clone(),
78            Self::Float(f) => format!("{}", f),
79            other => other.repr(),
80        }
81    }
82
83    fn repr(&self) -> String {
84        match self {
85            Self::None => "None".to_string(),
86            Self::Bool(b) => {
87                if *b {
88                    "True".to_string()
89                } else {
90                    "False".to_string()
91                }
92            }
93            Self::Int(i) => format!("{}", i),
94            Self::Float(f) => {
95                if f.fract() == 0.0 {
96                    format!("{}.0", f)
97                }
98                else {
99                    format!("{}", f)
100                }
101            }
102            Self::String(s) => {
103                let mut ret = String::with_capacity(s.len() + 2);
104                ret.push('"');
105
106                for ch in s.chars() {
107                    match ch {
108                        '\\' => ret.push_str("\\\\"),
109                        '\"' => ret.push_str("\\\""),
110                        '\n' => ret.push_str("\\n"),
111                        '\r' => ret.push_str("\\r"),
112                        '\t' => ret.push_str("\\t"),
113                        ch => ret.push(ch),
114                    }
115                }
116
117                ret.push('"');
118                ret
119            }
120            Self::List(l) => todo!(),
121            Self::Dict(d) => todo!(),
122        }
123    }
124}
125
126#[test]
127fn test_none() {
128    let none = Value::None;
129    assert_eq!(none.to_bool(), false);
130    assert_eq!(none.to_i64(), 0i64);
131    assert_eq!(none.to_f64(), 0f64);
132    assert_eq!(none.to_string(), "None");
133    assert_eq!(none.repr(), "None");
134}
135
136#[test]
137fn test_bool() {
138    // True
139    let t = Value::Bool(true);
140
141    assert_eq!(t.to_bool(), true);
142    assert_eq!(t.to_i64(), 1i64);
143    assert_eq!(t.to_f64(), 1f64);
144    assert_eq!(t.to_string(), "True");
145    assert_eq!(t.repr(), "True");
146
147    // False
148    let f = Value::Bool(false);
149
150    assert_eq!(f.to_bool(), false);
151    assert_eq!(f.to_i64(), 0i64);
152    assert_eq!(f.to_f64(), 0f64);
153    assert_eq!(f.to_string(), "False");
154    assert_eq!(f.repr(), "False");
155
156    let i = Value::Int(42);
157    assert_eq!(i.to_i64(), 42i64);
158    assert_eq!(i.to_f64(), 42f64);
159
160    let f = Value::Float(3.1415);
161    assert_eq!(f.to_i64(), 3i64);
162    assert_eq!(f.to_f64(), 3.1415f64);
163}
164
165#[test]
166fn test_int() {
167    let i = Value::Int(42);
168    assert_eq!(i.to_bool(), true);
169    assert_eq!(i.to_i64(), 42i64);
170    assert_eq!(i.to_f64(), 42f64);
171    assert_eq!(i.to_string(), "42");
172    assert_eq!(i.repr(), "42");
173
174    let i = Value::Int(0);
175    assert_eq!(i.to_bool(), false);
176    assert_eq!(i.to_i64(), 0i64);
177    assert_eq!(i.to_f64(), 0f64);
178    assert_eq!(i.to_string(), "0");
179    assert_eq!(i.repr(), "0");
180}
181
182#[test]
183fn test_float() {
184    let f = Value::Float(3.1415);
185    assert_eq!(f.to_bool(), true);
186    assert_eq!(f.to_i64(), 3i64);
187    assert_eq!(f.to_f64(), 3.1415f64);
188    assert_eq!(f.to_string(), "3.1415");
189    assert_eq!(f.repr(), "3.1415");
190
191    let f = Value::Float(1337f64);
192    assert_eq!(f.to_bool(), true);
193    assert_eq!(f.to_i64(), 1337i64);
194    assert_eq!(f.to_f64(), 1337f64);
195    assert_eq!(f.to_string(), "1337");
196    assert_eq!(f.repr(), "1337.0");
197}
198
199#[test]
200fn test_string() {
201    let s = Value::String("Hello".to_string());
202    assert_eq!(s.to_bool(), true);
203    assert_eq!(s.to_i64(), 0i64);
204    assert_eq!(s.to_f64(), 0f64);
205    assert_eq!(s.to_string(), "Hello");
206    assert_eq!(s.repr(), "\"Hello\"");
207
208    let s = Value::String("".to_string());
209    assert_eq!(s.to_bool(), false);
210    assert_eq!(s.to_i64(), 0i64);
211    assert_eq!(s.to_f64(), 0f64);
212    assert_eq!(s.to_string(), "");
213    assert_eq!(s.repr(), "\"\"");
214
215    let s = Value::String("42".to_string());
216    assert_eq!(s.to_bool(), true);
217    assert_eq!(s.to_i64(), 42i64);
218    assert_eq!(s.to_f64(), 42f64);
219    assert_eq!(s.to_string(), "42");
220    assert_eq!(s.repr(), "\"42\"");
221
222    let s = Value::String("3.1415".to_string());
223    assert_eq!(s.to_bool(), true);
224    assert_eq!(s.to_i64(), 3i64);
225    assert_eq!(s.to_f64(), 3.1415f64);
226    assert_eq!(s.to_string(), "3.1415");
227    assert_eq!(s.repr(), "3.1415");
228}