lasm/
value.rs

1use std::default::Default;
2use std::fmt::Display;
3
4#[derive(Clone, Debug, PartialEq)]
5pub enum Value {
6    Int(i64),
7    Float(f64),
8    String(String),
9    Ptr(*mut u8),
10    Null,
11}
12
13impl Into<Value> for i64 {
14    fn into(self) -> Value {
15        Value::Int(self)
16    }
17}
18
19impl Into<Value> for f64 {
20    fn into(self) -> Value {
21        Value::Float(self)
22    }
23}
24
25impl Into<Value> for String {
26    fn into(self) -> Value {
27        Value::String(self)
28    }
29}
30
31impl Into<Value> for *mut u8 {
32    fn into(self) -> Value {
33        Value::Ptr(self)
34    }
35}
36
37impl Default for Value {
38    fn default() -> Self {
39        Value::Null
40    }
41}
42
43impl Display for Value {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        match self {
46            Value::Int(i) => write!(f, "{}", i),
47            Value::Float(fl) => write!(f, "{}", fl),
48            Value::String(s) => write!(f, "\"{}\"", s),
49            Value::Ptr(p) => write!(f, "Ptr({:p})", p),
50            Value::Null => write!(f, "Null"),
51        }
52    }
53}
54
55impl Value {
56    pub fn as_int(&self) -> Option<i64> {
57        match self {
58            Value::Int(i) => Some(*i),
59            _ => None,
60        }
61    }
62
63    pub fn as_float(&self) -> Option<f64> {
64        match self {
65            Value::Float(f) => Some(*f),
66            _ => None,
67        }
68    }
69
70    pub fn as_string(&self) -> Option<&str> {
71        match self {
72            Value::String(s) => Some(s),
73            _ => None,
74        }
75    }
76
77    pub fn as_ptr(&self) -> Option<*mut u8> {
78        match self {
79            Value::Ptr(p) => Some(*p),
80            _ => None,
81        }
82    }
83
84    pub fn to_str(&self) -> Value {
85        match self {
86            Value::Int(i) => {
87                if (0..=255).contains(i) {
88                    if let Some(c) = char::from_u32(*i as u32) {
89                        Value::String(c.to_string())
90                    } else {
91                        Value::String(i.to_string())
92                    }
93                } else {
94                    Value::String(i.to_string())
95                }
96            }
97            Value::Float(f) => {
98                let bits = f.to_bits() as i64;
99                if (0..=255).contains(&bits) {
100                    if let Some(c) = char::from_u32(bits as u32) {
101                        Value::String(c.to_string())
102                    } else {
103                        Value::String(f.to_string())
104                    }
105                } else {
106                    Value::String(f.to_string())
107                }
108            }
109            Value::String(s) => Value::String(s.clone()),
110            Value::Ptr(p) => {
111                use std::ffi::CStr;
112                unsafe {
113                    match CStr::from_ptr(*p as *const i8).to_str() {
114                        Ok(s) => Value::String(s.to_string()),
115                        Err(_) => Value::String("<invalid utf8>".to_string()),
116                    }
117                }
118            }
119            Value::Null => Value::String("null".to_string()),
120        }
121    }
122}