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