1use std::sync::Arc;
9use indexmap::IndexMap;
10use serde_json::{Map, Number};
11
12#[derive(Clone, Debug)]
15pub enum Val {
16 Null,
17 Bool(bool),
18 Int(i64),
19 Float(f64),
20 Str(Arc<str>),
21 Arr(Arc<Vec<Val>>),
22 Obj(Arc<IndexMap<Arc<str>, Val>>),
23}
24
25thread_local! {
28 static NULL_VAL: Val = Val::Null;
29}
30
31impl Val {
34 #[inline]
36 pub fn get_field(&self, key: &str) -> Val {
37 match self {
38 Val::Obj(m) => m.get(key).cloned().unwrap_or(Val::Null),
39 _ => Val::Null,
40 }
41 }
42
43 #[inline]
45 pub fn get_index(&self, i: i64) -> Val {
46 match self {
47 Val::Arr(a) => {
48 let idx = if i < 0 {
49 a.len().saturating_sub(i.unsigned_abs() as usize)
50 } else { i as usize };
51 a.get(idx).cloned().unwrap_or(Val::Null)
52 }
53 _ => Val::Null,
54 }
55 }
56
57 #[inline] pub fn is_null(&self) -> bool { matches!(self, Val::Null) }
58 #[inline] pub fn is_bool(&self) -> bool { matches!(self, Val::Bool(_)) }
59 #[inline] pub fn is_number(&self) -> bool { matches!(self, Val::Int(_) | Val::Float(_)) }
60 #[inline] pub fn is_string(&self) -> bool { matches!(self, Val::Str(_)) }
61 #[inline] pub fn is_array(&self) -> bool { matches!(self, Val::Arr(_)) }
62 #[inline] pub fn is_object(&self) -> bool { matches!(self, Val::Obj(_)) }
63
64 #[inline]
65 pub fn as_bool(&self) -> Option<bool> {
66 if let Val::Bool(b) = self { Some(*b) } else { None }
67 }
68
69 #[inline]
70 pub fn as_i64(&self) -> Option<i64> {
71 match self { Val::Int(n) => Some(*n), Val::Float(f) => Some(*f as i64), _ => None }
72 }
73
74 #[inline]
75 pub fn as_f64(&self) -> Option<f64> {
76 match self { Val::Float(f) => Some(*f), Val::Int(n) => Some(*n as f64), _ => None }
77 }
78
79 #[inline]
80 pub fn as_str(&self) -> Option<&str> {
81 if let Val::Str(s) = self { Some(s) } else { None }
82 }
83
84 #[inline]
85 pub fn as_array(&self) -> Option<&[Val]> {
86 if let Val::Arr(a) = self { Some(a) } else { None }
87 }
88
89 pub fn as_array_mut(&mut self) -> Option<&mut Vec<Val>> {
90 if let Val::Arr(a) = self { Some(Arc::make_mut(a)) } else { None }
91 }
92
93 #[inline]
94 pub fn as_object(&self) -> Option<&IndexMap<Arc<str>, Val>> {
95 if let Val::Obj(m) = self { Some(m) } else { None }
96 }
97
98 pub fn as_object_mut(&mut self) -> Option<&mut IndexMap<Arc<str>, Val>> {
99 if let Val::Obj(m) = self { Some(Arc::make_mut(m)) } else { None }
100 }
101
102 pub fn get(&self, key: &str) -> Option<&Val> {
104 match self {
105 Val::Obj(m) => m.get(key),
106 _ => None,
107 }
108 }
109
110 pub fn type_name(&self) -> &'static str {
111 match self {
112 Val::Null => "null",
113 Val::Bool(_) => "bool",
114 Val::Int(_) | Val::Float(_) => "number",
115 Val::Str(_) => "string",
116 Val::Arr(_) => "array",
117 Val::Obj(_) => "object",
118 }
119 }
120
121 pub fn into_vec(self) -> Option<Vec<Val>> {
123 if let Val::Arr(a) = self {
124 Some(Arc::try_unwrap(a).unwrap_or_else(|a| (*a).clone()))
125 } else { None }
126 }
127
128 pub fn into_map(self) -> Option<IndexMap<Arc<str>, Val>> {
130 if let Val::Obj(m) = self {
131 Some(Arc::try_unwrap(m).unwrap_or_else(|m| (*m).clone()))
132 } else { None }
133 }
134
135 #[inline]
137 pub fn arr(v: Vec<Val>) -> Self { Val::Arr(Arc::new(v)) }
138
139 #[inline]
141 pub fn obj(m: IndexMap<Arc<str>, Val>) -> Self { Val::Obj(Arc::new(m)) }
142
143 #[inline]
145 pub fn key(s: &str) -> Arc<str> { Arc::from(s) }
146}
147
148impl From<&serde_json::Value> for Val {
151 fn from(v: &serde_json::Value) -> Self {
152 match v {
153 serde_json::Value::Null => Val::Null,
154 serde_json::Value::Bool(b) => Val::Bool(*b),
155 serde_json::Value::Number(n) => {
156 if let Some(i) = n.as_i64() { Val::Int(i) }
157 else { Val::Float(n.as_f64().unwrap_or(0.0)) }
158 }
159 serde_json::Value::String(s) => Val::Str(Arc::from(s.as_str())),
160 serde_json::Value::Array(a) => Val::Arr(Arc::new(a.iter().map(Val::from).collect())),
161 serde_json::Value::Object(m) => Val::Obj(Arc::new(
162 m.iter().map(|(k, v)| (Arc::from(k.as_str()), Val::from(v))).collect()
163 )),
164 }
165 }
166}
167
168impl From<Val> for serde_json::Value {
169 fn from(v: Val) -> Self {
170 match v {
171 Val::Null => serde_json::Value::Null,
172 Val::Bool(b) => serde_json::Value::Bool(b),
173 Val::Int(n) => serde_json::Value::Number(n.into()),
174 Val::Float(f) => serde_json::Value::Number(
175 Number::from_f64(f).unwrap_or_else(|| 0.into())
176 ),
177 Val::Str(s) => serde_json::Value::String(s.to_string()),
178 Val::Arr(a) => serde_json::Value::Array(
179 Arc::try_unwrap(a).unwrap_or_else(|a| (*a).clone())
180 .into_iter().map(serde_json::Value::from).collect()
181 ),
182 Val::Obj(m) => {
183 let map: Map<String, serde_json::Value> =
184 Arc::try_unwrap(m).unwrap_or_else(|m| (*m).clone())
185 .into_iter()
186 .map(|(k, v)| (k.to_string(), serde_json::Value::from(v)))
187 .collect();
188 serde_json::Value::Object(map)
189 }
190 }
191 }
192}
193
194impl PartialEq for Val {
197 fn eq(&self, other: &Self) -> bool {
198 match (self, other) {
199 (Val::Null, Val::Null) => true,
200 (Val::Bool(a), Val::Bool(b)) => a == b,
201 (Val::Str(a), Val::Str(b)) => a == b,
202 (Val::Int(a), Val::Int(b)) => a == b,
203 (Val::Float(a), Val::Float(b)) => a == b,
204 (Val::Int(a), Val::Float(b)) => (*a as f64) == *b,
205 (Val::Float(a), Val::Int(b)) => *a == (*b as f64),
206 _ => false,
207 }
208 }
209}
210
211impl Eq for Val {}
212
213impl std::hash::Hash for Val {
214 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
215 match self {
216 Val::Null => 0u8.hash(state),
217 Val::Bool(b) => { 1u8.hash(state); b.hash(state); }
218 Val::Int(n) => { 2u8.hash(state); n.hash(state); }
219 Val::Float(f) => { 2u8.hash(state); f.to_bits().hash(state); }
220 Val::Str(s) => { 3u8.hash(state); s.hash(state); }
221 Val::Arr(a) => { 4u8.hash(state); (Arc::as_ptr(a) as usize).hash(state); }
222 Val::Obj(m) => { 5u8.hash(state); (Arc::as_ptr(m) as usize).hash(state); }
223 }
224 }
225}
226
227impl std::fmt::Display for Val {
230 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
231 match self {
232 Val::Null => write!(f, "null"),
233 Val::Bool(b) => write!(f, "{}", b),
234 Val::Int(n) => write!(f, "{}", n),
235 Val::Float(fl) => write!(f, "{}", fl),
236 Val::Str(s) => write!(f, "{}", s),
237 other => write!(f, "{}", serde_json::Value::from(other.clone())),
238 }
239 }
240}