schema_core/common/
generic_value.rs1use std::collections::BTreeMap;
2use std::fmt;
3
4use rust_decimal::Decimal;
5use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
6use serde::{Deserialize, Serialize, Serializer};
7
8#[derive(Debug, Clone, Hash, PartialEq, Eq)]
9pub enum GenericValue {
10 Null,
11 Bool(bool),
12 Int(i64),
13 Decimal(Decimal),
14 String(String),
15 Array(Vec<GenericValue>),
16 Map(BTreeMap<String, GenericValue>),
17}
18
19impl GenericValue {
20 pub fn is_bindable_scalar(&self) -> bool {
27 match self {
28 GenericValue::Bool(_)
29 | GenericValue::Int(_)
30 | GenericValue::Decimal(_)
31 | GenericValue::String(_) => true,
32 GenericValue::Null | GenericValue::Array(_) | GenericValue::Map(_) => false,
33 }
34 }
35}
36
37impl Serialize for GenericValue {
42 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
43 match self {
44 GenericValue::Null => serializer.serialize_none(),
45 GenericValue::Bool(value) => serializer.serialize_bool(*value),
46 GenericValue::Int(value) => serializer.serialize_i64(*value),
47 GenericValue::Decimal(value) => Serialize::serialize(value, serializer),
50 GenericValue::String(value) => serializer.serialize_str(value),
51 GenericValue::Array(items) => items.serialize(serializer),
52 GenericValue::Map(map) => map.serialize(serializer),
53 }
54 }
55}
56
57impl<'de> Deserialize<'de> for GenericValue {
64 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
65 struct GenericValueVisitor;
66
67 impl<'de> Visitor<'de> for GenericValueVisitor {
68 type Value = GenericValue;
69
70 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 f.write_str("any JSON-like value")
72 }
73
74 fn visit_bool<E>(self, v: bool) -> Result<GenericValue, E> {
75 Ok(GenericValue::Bool(v))
76 }
77
78 fn visit_i64<E>(self, v: i64) -> Result<GenericValue, E> {
79 Ok(GenericValue::Int(v))
80 }
81
82 fn visit_u64<E>(self, v: u64) -> Result<GenericValue, E> {
83 match i64::try_from(v) {
84 Ok(i) => Ok(GenericValue::Int(i)),
85 Err(_) => Ok(GenericValue::Decimal(Decimal::from(v))),
86 }
87 }
88
89 fn visit_f64<E: de::Error>(self, v: f64) -> Result<GenericValue, E> {
90 Decimal::try_from(v)
91 .map(GenericValue::Decimal)
92 .map_err(E::custom)
93 }
94
95 fn visit_str<E>(self, v: &str) -> Result<GenericValue, E> {
96 Ok(GenericValue::String(v.to_owned()))
97 }
98
99 fn visit_string<E>(self, v: String) -> Result<GenericValue, E> {
100 Ok(GenericValue::String(v))
101 }
102
103 fn visit_none<E>(self) -> Result<GenericValue, E> {
104 Ok(GenericValue::Null)
105 }
106
107 fn visit_unit<E>(self) -> Result<GenericValue, E> {
108 Ok(GenericValue::Null)
109 }
110
111 fn visit_some<D: Deserializer<'de>>(self, d: D) -> Result<GenericValue, D::Error> {
112 GenericValue::deserialize(d)
113 }
114
115 fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<GenericValue, A::Error> {
116 let mut items = Vec::new();
117 while let Some(item) = seq.next_element()? {
118 items.push(item);
119 }
120 Ok(GenericValue::Array(items))
121 }
122
123 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<GenericValue, A::Error> {
124 let mut out = BTreeMap::new();
125 while let Some((key, value)) = map.next_entry()? {
126 out.insert(key, value);
127 }
128 Ok(GenericValue::Map(out))
129 }
130 }
131
132 deserializer.deserialize_any(GenericValueVisitor)
133 }
134}