1use std::collections::HashMap;
4use std::fmt;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum ValueType {
9 Null,
11 Bool,
13 Int,
15 Float,
17 String,
19 List,
21 Map,
23 Function,
25 Bytes,
27 Error,
29}
30
31impl fmt::Display for ValueType {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 ValueType::Null => write!(f, "null"),
35 ValueType::Bool => write!(f, "bool"),
36 ValueType::Int => write!(f, "int"),
37 ValueType::Float => write!(f, "float"),
38 ValueType::String => write!(f, "string"),
39 ValueType::List => write!(f, "list"),
40 ValueType::Map => write!(f, "map"),
41 ValueType::Function => write!(f, "function"),
42 ValueType::Bytes => write!(f, "bytes"),
43 ValueType::Error => write!(f, "error"),
44 }
45 }
46}
47
48#[derive(Debug, Clone, PartialEq)]
53pub enum Value {
54 Null,
56 Bool(bool),
58 Int(i64),
60 Float(f64),
62 String(String),
64 List(Vec<Value>),
66 Map(HashMap<String, Value>),
68 Function(FunctionRef),
70 Bytes(Vec<u8>),
72 Error(String),
74}
75
76#[derive(Debug, Clone, PartialEq)]
78pub struct FunctionRef {
79 pub(crate) id: u64,
81 pub(crate) name: Option<String>,
83}
84
85impl FunctionRef {
86 pub fn name(&self) -> Option<&str> {
88 self.name.as_deref()
89 }
90}
91
92impl Value {
93 pub fn value_type(&self) -> ValueType {
95 match self {
96 Value::Null => ValueType::Null,
97 Value::Bool(_) => ValueType::Bool,
98 Value::Int(_) => ValueType::Int,
99 Value::Float(_) => ValueType::Float,
100 Value::String(_) => ValueType::String,
101 Value::List(_) => ValueType::List,
102 Value::Map(_) => ValueType::Map,
103 Value::Function(_) => ValueType::Function,
104 Value::Bytes(_) => ValueType::Bytes,
105 Value::Error(_) => ValueType::Error,
106 }
107 }
108
109 pub fn is_null(&self) -> bool {
111 matches!(self, Value::Null)
112 }
113
114 pub fn is_error(&self) -> bool {
116 matches!(self, Value::Error(_))
117 }
118
119 pub fn as_bool(&self) -> Option<bool> {
121 match self {
122 Value::Bool(b) => Some(*b),
123 _ => None,
124 }
125 }
126
127 pub fn as_int(&self) -> Option<i64> {
129 match self {
130 Value::Int(i) => Some(*i),
131 _ => None,
132 }
133 }
134
135 pub fn as_float(&self) -> Option<f64> {
137 match self {
138 Value::Float(f) => Some(*f),
139 Value::Int(i) => Some(*i as f64),
140 _ => None,
141 }
142 }
143
144 pub fn as_str(&self) -> Option<&str> {
146 match self {
147 Value::String(s) => Some(s.as_str()),
148 _ => None,
149 }
150 }
151
152 pub fn as_list(&self) -> Option<&[Value]> {
154 match self {
155 Value::List(l) => Some(l.as_slice()),
156 _ => None,
157 }
158 }
159
160 pub fn as_map(&self) -> Option<&HashMap<String, Value>> {
162 match self {
163 Value::Map(m) => Some(m),
164 _ => None,
165 }
166 }
167
168 pub fn as_bytes(&self) -> Option<&[u8]> {
170 match self {
171 Value::Bytes(b) => Some(b.as_slice()),
172 _ => None,
173 }
174 }
175
176 pub fn as_error(&self) -> Option<&str> {
178 match self {
179 Value::Error(e) => Some(e.as_str()),
180 _ => None,
181 }
182 }
183
184 pub fn null() -> Self {
186 Value::Null
187 }
188
189 pub fn error(msg: impl Into<String>) -> Self {
191 Value::Error(msg.into())
192 }
193}
194
195impl Default for Value {
196 fn default() -> Self {
197 Value::Null
198 }
199}
200
201impl fmt::Display for Value {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 match self {
204 Value::Null => write!(f, "null"),
205 Value::Bool(b) => write!(f, "{}", b),
206 Value::Int(i) => write!(f, "{}", i),
207 Value::Float(fl) => write!(f, "{}", fl),
208 Value::String(s) => write!(f, "\"{}\"", s),
209 Value::List(l) => {
210 write!(f, "[")?;
211 for (i, v) in l.iter().enumerate() {
212 if i > 0 {
213 write!(f, ", ")?;
214 }
215 write!(f, "{}", v)?;
216 }
217 write!(f, "]")
218 }
219 Value::Map(m) => {
220 write!(f, "{{")?;
221 for (i, (k, v)) in m.iter().enumerate() {
222 if i > 0 {
223 write!(f, ", ")?;
224 }
225 write!(f, "\"{}\": {}", k, v)?;
226 }
227 write!(f, "}}")
228 }
229 Value::Function(fr) => {
230 if let Some(name) = &fr.name {
231 write!(f, "<function {}>", name)
232 } else {
233 write!(f, "<function>")
234 }
235 }
236 Value::Bytes(b) => write!(f, "<bytes len={}>", b.len()),
237 Value::Error(e) => write!(f, "<error: {}>", e),
238 }
239 }
240}
241
242impl From<bool> for Value {
244 fn from(b: bool) -> Self {
245 Value::Bool(b)
246 }
247}
248
249impl From<i64> for Value {
250 fn from(i: i64) -> Self {
251 Value::Int(i)
252 }
253}
254
255impl From<i32> for Value {
256 fn from(i: i32) -> Self {
257 Value::Int(i as i64)
258 }
259}
260
261impl From<f64> for Value {
262 fn from(f: f64) -> Self {
263 Value::Float(f)
264 }
265}
266
267impl From<f32> for Value {
268 fn from(f: f32) -> Self {
269 Value::Float(f as f64)
270 }
271}
272
273impl From<String> for Value {
274 fn from(s: String) -> Self {
275 Value::String(s)
276 }
277}
278
279impl From<&str> for Value {
280 fn from(s: &str) -> Self {
281 Value::String(s.to_string())
282 }
283}
284
285impl From<HashMap<String, Value>> for Value {
289 fn from(m: HashMap<String, Value>) -> Self {
290 Value::Map(m)
291 }
292}
293
294impl From<Vec<u8>> for Value {
295 fn from(b: Vec<u8>) -> Self {
296 Value::Bytes(b)
297 }
298}
299
300impl<T: Into<Value>> From<Option<T>> for Value {
301 fn from(opt: Option<T>) -> Self {
302 match opt {
303 Some(v) => v.into(),
304 None => Value::Null,
305 }
306 }
307}
308
309#[cfg(test)]
310mod tests {
311 use super::*;
312
313 #[test]
314 fn test_value_types() {
315 assert_eq!(Value::Null.value_type(), ValueType::Null);
316 assert_eq!(Value::Bool(true).value_type(), ValueType::Bool);
317 assert_eq!(Value::Int(42).value_type(), ValueType::Int);
318 assert_eq!(Value::Float(3.14).value_type(), ValueType::Float);
319 assert_eq!(Value::String("hello".into()).value_type(), ValueType::String);
320 assert_eq!(Value::List(vec![]).value_type(), ValueType::List);
321 assert_eq!(Value::Map(HashMap::new()).value_type(), ValueType::Map);
322 }
323
324 #[test]
325 fn test_value_accessors() {
326 assert!(Value::Null.is_null());
327 assert!(!Value::Bool(true).is_null());
328
329 assert_eq!(Value::Bool(true).as_bool(), Some(true));
330 assert_eq!(Value::Int(42).as_bool(), None);
331
332 assert_eq!(Value::Int(42).as_int(), Some(42));
333 assert_eq!(Value::Float(3.14).as_float(), Some(3.14));
334 assert_eq!(Value::Int(42).as_float(), Some(42.0));
335
336 assert_eq!(Value::String("test".into()).as_str(), Some("test"));
337 }
338
339 #[test]
340 fn test_value_from_impls() {
341 let v: Value = true.into();
342 assert_eq!(v, Value::Bool(true));
343
344 let v: Value = 42i64.into();
345 assert_eq!(v, Value::Int(42));
346
347 let v: Value = "hello".into();
348 assert_eq!(v, Value::String("hello".into()));
349
350 let v: Value = None::<i64>.into();
351 assert!(v.is_null());
352
353 let v: Value = Some(42i64).into();
354 assert_eq!(v, Value::Int(42));
355 }
356
357 #[test]
358 fn test_value_display() {
359 assert_eq!(format!("{}", Value::Null), "null");
360 assert_eq!(format!("{}", Value::Bool(true)), "true");
361 assert_eq!(format!("{}", Value::Int(42)), "42");
362 assert_eq!(format!("{}", Value::String("test".into())), "\"test\"");
363 }
364}