1use serde::{de::Visitor, Deserialize, Serialize};
2
3use crate::{
4 data::{Object, ObjectVisitor},
5 Variable,
6};
7
8#[derive(Clone, Debug)]
9pub enum Value {
10 None,
11 Bool(bool),
12 Int(i64),
13 Float(f64),
14 String(String),
15 Variable(Variable),
16 Object(Object),
17 Array(Vec<Value>),
18}
19
20impl<'de> Deserialize<'de> for Value {
21 fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
22 where
23 D: serde::Deserializer<'de>,
24 {
25 deserializer.deserialize_any(ValueVisitor::new())
26 }
27}
28
29#[derive(Clone, Copy, Debug)]
30struct ValueVisitor {}
31
32impl ValueVisitor {
33 fn new() -> Self {
34 Self {}
35 }
36}
37
38impl<'de> Visitor<'de> for ValueVisitor {
39 type Value = Value;
40
41 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
42 formatter.write_str("any value")
43 }
44
45 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
46 where
47 E: serde::de::Error,
48 {
49 Ok(v.into())
50 }
51
52 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
53 where
54 E: serde::de::Error,
55 {
56 Ok(v.into())
57 }
58
59 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
60 where
61 E: serde::de::Error,
62 {
63 Ok(v.into())
64 }
65
66 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
67 where
68 E: serde::de::Error,
69 {
70 Ok(v.into())
71 }
72
73 fn visit_none<E>(self) -> Result<Self::Value, E>
74 where
75 E: serde::de::Error,
76 {
77 Ok(Value::None)
78 }
79
80 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
81 where
82 E: serde::de::Error,
83 {
84 Ok(v.into())
85 }
86
87 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
88 where
89 A: serde::de::MapAccess<'de>,
90 {
91 Ok(ObjectVisitor::new().visit_map(map)?.into())
92 }
93
94 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
95 where
96 E: serde::de::Error,
97 {
98 Ok(v.into())
99 }
100
101 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
102 where
103 E: serde::de::Error,
104 {
105 Ok(v.into())
106 }
107
108 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
109 where
110 A: serde::de::SeqAccess<'de>,
111 {
112 let mut vec: Vec<Value> = Vec::new();
113 while let Some(value) = seq.next_element::<Value>()? {
114 vec.push(value);
115 }
116 Ok(vec.into())
117 }
118
119 fn visit_unit<E>(self) -> Result<Self::Value, E>
120 where
121 E: serde::de::Error,
122 {
123 Ok(Value::None)
124 }
125}
126
127impl Serialize for Value {
128 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
129 where
130 S: serde::Serializer,
131 {
132 match self {
133 Value::None => serializer.serialize_none(),
134 Value::Bool(b) => serializer.serialize_bool(*b),
135 Value::Int(i) => serializer.serialize_i64(*i),
136 Value::Float(f) => serializer.serialize_f64(*f),
137 Value::String(s) => serializer.serialize_str(s),
138 Value::Variable(v) => v.serialize(serializer),
139 Value::Object(o) => o.serialize(serializer),
140 Value::Array(a) => a.serialize(serializer),
141 }
142 }
143}
144
145macro_rules! into {
146 ($($v:ident, $e:ident)*) => {
147 $(
148 impl From<$v> for Value {
149 fn from(v: $v) -> Self {
150 Self::$e(v.try_into().unwrap())
151 }
152 }
153 )*
154 };
155}
156
157macro_rules! from {
158 ($($f:ident, $v:ident)*) => {
159 $(
160 impl From<Value> for $v {
161 fn from(v: Value) -> Self {
162 paste::paste! {
163 v.[<as_ $f>]().unwrap()
164 }
165 }
166 }
167
168 impl From<&Value> for $v {
169 fn from(v: &Value) -> Self {
170 paste::paste! {
171 v.[<as_ $f>]().unwrap()
172 }
173 }
174 }
175
176 impl From<Value> for Option<$v> {
177 fn from(v: Value) -> Self {
178 match v {
179 Value::None => None,
180 _ => Some(paste::paste! { v.[<as_ $f>]().unwrap() }),
181 }
182 }
183 }
184
185 impl From<&Value> for Option<$v> {
186 fn from(v: &Value) -> Self {
187 match v {
188 Value::None => None,
189 _ => Some(paste::paste! { v.[<as_ $f>]().unwrap() }),
190 }
191 }
192 }
193 )*
194 };
195}
196
197type VecValue = Vec<Value>;
198
199into!(
200 bool, Bool
201 i8, Int
202 i16, Int
203 i32, Int
204 i64, Int
205 u64, Int
206 f64, Float
207 String, String
208 Object, Object
209 VecValue, Array
210);
211
212from!(
213 bool, bool
214 i8, i8
215 i16, i16
216 i32, i32
217 i64, i64
218 u64, u64
219 f64, f64
220 string, String
221 object, Object
222 array, VecValue
223);
224
225#[cfg(feature = "uuid")]
226use uuid::Uuid;
227
228#[cfg(feature = "uuid")]
229from!(uuid, Uuid);
230
231#[cfg(feature = "bigdecimal")]
232use bigdecimal::BigDecimal;
233
234#[cfg(feature = "bigdecimal")]
235from!(bigdecimal, BigDecimal);
236
237#[cfg(feature = "time")]
238use time::OffsetDateTime;
239
240#[cfg(feature = "time")]
241from!(time, OffsetDateTime);
242
243#[cfg(feature = "chrono")]
244use chrono::{DateTime, Utc};
245
246#[cfg(feature = "chrono")]
247type Chrono = DateTime<Utc>;
248#[cfg(feature = "chrono")]
249from!(chrono, Chrono);
250
251impl From<Variable> for Value {
252 fn from(v: Variable) -> Self {
253 Self::Variable(v)
254 }
255}
256
257impl From<&str> for Value {
258 fn from(v: &str) -> Self {
259 Self::String(v.into())
260 }
261}
262
263impl<'a> From<&'a Value> for &'a str {
264 fn from(v: &'a Value) -> Self {
265 v.as_str().unwrap()
266 }
267}
268
269impl<'a> From<&'a Value> for Option<&'a str> {
270 fn from(v: &'a Value) -> Self {
271 match v {
272 Value::None => None,
273 _ => Some(v.as_str().unwrap()),
274 }
275 }
276}
277
278impl Value {
279 pub fn as_i8(&self) -> Option<i8> {
280 match self {
281 Value::Int(v) => Some(*v as i8),
282 Value::Float(v) => Some(*v as i8),
283 Value::String(v) => v.parse().ok(),
284 _ => None,
285 }
286 }
287
288 pub fn as_i16(&self) -> Option<i16> {
289 match self {
290 Value::Int(v) => Some(*v as i16),
291 Value::Float(v) => Some(*v as i16),
292 Value::String(v) => v.parse().ok(),
293 _ => None,
294 }
295 }
296
297 pub fn as_i32(&self) -> Option<i32> {
298 match self {
299 Value::Int(v) => Some(*v as i32),
300 Value::Float(v) => Some(*v as i32),
301 Value::String(v) => v.parse().ok(),
302 _ => None,
303 }
304 }
305
306 pub fn as_i64(&self) -> Option<i64> {
307 match self {
308 Value::Int(v) => Some(*v),
309 Value::Float(v) => Some(*v as i64),
310 Value::String(v) => v.parse().ok(),
311 _ => None,
312 }
313 }
314
315 pub fn as_u64(&self) -> Option<u64> {
316 match self {
317 Value::Int(v) => Some(*v as u64),
318 Value::Float(v) => Some(*v as u64),
319 Value::String(v) => v.parse().ok(),
320 _ => None,
321 }
322 }
323
324 pub fn as_f64(&self) -> Option<f64> {
325 match self {
326 Value::Int(v) => Some(*v as f64),
327 Value::Float(v) => Some(*v),
328 Value::String(v) => v.parse().ok(),
329 _ => None,
330 }
331 }
332
333 pub fn as_bool(&self) -> Option<bool> {
334 match self {
335 Value::Bool(v) => Some(*v),
336 Value::Int(v) => Some(*v != 0),
337 _ => None,
338 }
339 }
340
341 pub fn as_string(&self) -> Option<String> {
342 match self {
343 Value::String(v) => Some(v.clone()),
344 _ => None,
345 }
346 }
347
348 pub fn as_str(&self) -> Option<&str> {
349 match self {
350 Value::String(v) => Some(v),
351 _ => None,
352 }
353 }
354
355 pub fn as_object(&self) -> Option<Object> {
356 match self {
357 Value::Object(v) => Some(v.clone()),
358 _ => None,
359 }
360 }
361
362 pub fn parse_object(&self) -> Option<Object> {
363 match self {
364 Value::Object(v) => Some(v.clone()),
365 Value::String(v) => serde_json::from_str(v).ok(),
366 _ => None,
367 }
368 }
369
370 pub fn as_array(&self) -> Option<Vec<Value>> {
371 match self {
372 Value::Array(v) => Some(v.clone()),
373 _ => None,
374 }
375 }
376
377 #[cfg(feature = "uuid")]
378 pub fn as_uuid(&self) -> Option<uuid::Uuid> {
379 match self {
380 Value::String(v) => uuid::Uuid::parse_str(v.as_str()).ok(),
381 _ => None,
382 }
383 }
384
385 #[cfg(feature = "bigdecimal")]
386 pub fn as_bigdecimal(&self) -> Option<bigdecimal::BigDecimal> {
387 use std::str::FromStr;
388
389 use bigdecimal::FromPrimitive;
390
391 match self {
392 Value::Float(v) => bigdecimal::BigDecimal::from_f64(*v),
393 Value::Int(v) => bigdecimal::BigDecimal::from_i64(*v),
394 Value::String(v) => bigdecimal::BigDecimal::from_str(v.as_str()).ok(),
395 _ => None,
396 }
397 }
398
399 #[cfg(feature = "time")]
400 pub fn as_time(&self) -> Option<time::OffsetDateTime> {
401 match self {
402 Value::String(v) => {
403 if v.as_str() == "0000-00-00" || v.starts_with('-') {
404 Some(time::OffsetDateTime::UNIX_EPOCH)
405 } else if v.len() == 10 {
406 time::OffsetDateTime::parse(
407 format!("{}T00:00:00Z", v).as_str(),
408 &time::format_description::well_known::Iso8601::DEFAULT,
409 )
410 .ok()
411 } else {
412 time::OffsetDateTime::parse(
413 v.as_str(),
414 &time::format_description::well_known::Iso8601::DEFAULT,
415 )
416 .ok()
417 }
418 },
419 _ => None,
420 }
421 }
422
423 #[cfg(feature = "chrono")]
424 pub fn as_chrono(&self) -> Option<chrono::DateTime<chrono::Utc>> {
425 match self {
426 Value::String(v) => {
427 if v.as_str() == "0000-00-00" || v.starts_with('-') {
428 Some(chrono::DateTime::<chrono::Utc>::MIN_UTC)
429 } else if v.len() == 10 {
430 chrono::DateTime::parse_from_rfc3339(format!("{}T00:00:00Z", v).as_str())
431 .ok()
432 .map(|v| v.with_timezone(&chrono::Utc))
433 } else {
434 chrono::DateTime::parse_from_rfc3339(v.as_str())
435 .ok()
436 .map(|v| v.with_timezone(&chrono::Utc))
437 }
438 },
439 _ => None,
440 }
441 }
442
443 pub fn string_to_value(&self) -> Option<Value> {
444 if let Some(s) = self.as_str() {
445 serde_json::from_str::<Value>(s).ok()
446 } else {
447 Some(self.clone())
448 }
449 }
450
451 pub fn is_string(&self) -> bool {
452 matches!(self, Value::String(_))
453 }
454}