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}