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 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 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}