1use crate::Error;
2use juniper::{DefaultScalarValue, FromInputValue, InputValue};
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::convert::{TryFrom, TryInto};
6use std::fmt::Result as FmtResult;
7use std::fmt::{Display, Formatter};
8use uuid::Uuid;
9
10#[derive(Clone, Debug, Deserialize, Serialize)]
23pub enum Value {
24 Array(Vec<Value>),
25 Bool(bool),
26 Float64(f64),
27 Int64(i64),
28 Map(HashMap<String, Value>),
29 Null,
30 String(String),
31 UInt64(u64),
32 Uuid(Uuid),
33}
34
35impl Display for Value {
36 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
37 write!(
38 f,
39 "{}",
40 match &self {
41 Value::Array(v) => {
42 let s = v
43 .iter()
44 .enumerate()
45 .fold("[".to_string(), |mut acc, (i, val)| {
46 if i > 0 {
47 acc.push_str(", ");
48 }
49
50 acc.push_str(&*format!("{}", val));
51 acc
52 });
53 s + "]"
54 }
55 Value::Bool(b) => b.to_string(),
56 Value::Float64(f) => f.to_string(),
57 Value::Int64(i) => i.to_string(),
58 Value::Map(m) => {
59 let s =
60 m.iter()
61 .enumerate()
62 .fold("[".to_string(), |mut acc, (i, (key, val))| {
63 if i > 0 {
64 acc.push_str(", ");
65 }
66
67 acc.push_str(&*format!("({}, {})", key, val));
68 acc
69 });
70
71 s + "]"
72 }
73 Value::Null => "{}".to_string(),
74 Value::String(s) => s.to_string(),
75 Value::UInt64(u) => u.to_string(),
76 Value::Uuid(uuid) => uuid.to_hyphenated().to_string(),
77 }
78 )
79 }
80}
81
82impl From<bool> for Value {
83 fn from(v: bool) -> Self {
84 Value::Bool(v)
85 }
86}
87
88impl From<f64> for Value {
89 fn from(v: f64) -> Self {
90 Value::Float64(v)
91 }
92}
93
94impl From<HashMap<String, Value>> for Value {
95 fn from(map: HashMap<String, Value>) -> Self {
96 Value::Map(map)
97 }
98}
99
100impl From<i64> for Value {
101 fn from(v: i64) -> Self {
102 Value::Int64(v)
103 }
104}
105
106impl From<String> for Value {
107 fn from(v: String) -> Self {
108 Value::String(v)
109 }
110}
111
112impl From<u64> for Value {
113 fn from(v: u64) -> Self {
114 Value::UInt64(v)
115 }
116}
117
118impl From<Uuid> for Value {
119 fn from(v: Uuid) -> Self {
120 Value::Uuid(v)
121 }
122}
123
124impl From<Vec<Value>> for Value {
125 fn from(v: Vec<Value>) -> Self {
126 Value::Array(v)
127 }
128}
129
130impl FromInputValue for Value {
131 fn from_input_value(v: &InputValue) -> Option<Self> {
132 match v {
133 InputValue::Scalar(scalar) => Some(match scalar {
134 DefaultScalarValue::Int(i) => Value::Int64(i64::from(*i)),
135 DefaultScalarValue::Float(f) => Value::Float64(*f),
136 DefaultScalarValue::String(s) => Value::String(s.to_string()),
137 DefaultScalarValue::Boolean(b) => Value::Bool(*b),
138 }),
139 _ => match serde_json::to_value(v) {
140 Err(_) => None,
141 Ok(serde_value) => match Value::try_from(serde_value) {
142 Ok(value) => Some(value),
143 _ => None,
144 },
145 },
146 }
147 }
148}
149
150impl PartialEq for Value {
151 fn eq(&self, other: &Value) -> bool {
152 match (self, other) {
153 (Value::Array(a), Value::Array(oa)) => a == oa,
154 (Value::Bool(b), Value::Bool(ob)) => b == ob,
155 (Value::Float64(f), Value::Float64(of)) => f == of,
156 (Value::Int64(i), Value::Int64(oi)) => i == oi,
157 (Value::Map(m), Value::Map(om)) => m == om,
158 (Value::Null, Value::Null) => true,
159 (Value::String(s), Value::String(os)) => s == os,
160 (Value::UInt64(i), Value::UInt64(oi)) => i == oi,
161 (_, _) => false,
162 }
163 }
164}
165
166impl TryFrom<serde_json::Value> for Value {
167 type Error = Error;
168
169 fn try_from(value: serde_json::Value) -> Result<Value, Error> {
170 match value {
171 serde_json::Value::Array(a) => Ok(Value::Array(
172 a.into_iter()
173 .map(|val| val.try_into())
174 .collect::<Result<Vec<_>, _>>()?,
175 )),
176 serde_json::Value::Bool(b) => Ok(Value::Bool(b)),
177 serde_json::Value::Null => Ok(Value::Null),
178 serde_json::Value::Number(n) => {
179 if let Some(i) = n.as_i64() {
180 Ok(Value::Int64(i))
181 } else if let Some(i) = n.as_u64() {
182 Ok(Value::UInt64(i))
183 } else if let Some(f) = n.as_f64() {
184 Ok(Value::Float64(f))
185 } else {
186 Err(Error::TypeConversionFailed {
187 src: "serde_json::Value::Number".to_string(),
188 dst: "Value".to_string(),
189 })
190 }
191 }
192 serde_json::Value::String(s) => Ok(Value::String(s)),
193 serde_json::Value::Object(m) => Ok(Value::Map(
194 m.into_iter()
195 .map(|(k, v)| {
196 let val = v.try_into()?;
197 Ok((k, val))
198 })
199 .collect::<Result<HashMap<String, Value>, Error>>()?,
200 )),
201 }
202 }
203}
204
205impl TryFrom<Value> for bool {
206 type Error = Error;
207
208 fn try_from(value: Value) -> Result<bool, Self::Error> {
209 if let Value::Bool(b) = value {
210 Ok(b)
211 } else {
212 Err(Error::TypeConversionFailed {
213 src: format!("{:#?}", value),
214 dst: "bool".to_string(),
215 })
216 }
217 }
218}
219
220impl TryFrom<Value> for f64 {
221 type Error = Error;
222
223 fn try_from(value: Value) -> Result<f64, Self::Error> {
224 if let Value::Int64(i) = value {
225 Ok(i as f64)
226 } else if let Value::UInt64(i) = value {
227 Ok(i as f64)
228 } else if let Value::Float64(f) = value {
229 Ok(f)
230 } else {
231 Err(Error::TypeConversionFailed {
232 src: format!("{:#?}", value),
233 dst: "f64".to_string(),
234 })
235 }
236 }
237}
238
239impl TryFrom<Value> for i32 {
240 type Error = Error;
241
242 fn try_from(value: Value) -> Result<i32, Self::Error> {
243 match value {
244 Value::Int64(i) => Ok(i32::try_from(i)?),
245 Value::UInt64(i) => Ok(i32::try_from(i)?),
246 _ => Err(Error::TypeConversionFailed {
247 src: format!("{:#?}", value),
248 dst: "i32".to_string(),
249 }),
250 }
251 }
252}
253
254impl TryFrom<Value> for String {
255 type Error = Error;
256
257 fn try_from(value: Value) -> Result<String, Self::Error> {
258 if let Value::String(s) = value {
259 Ok(s)
260 } else if let Value::Int64(i) = value {
261 Ok(i.to_string())
262 } else {
263 Err(Error::TypeConversionFailed {
264 src: format!("{:#?}", value),
265 dst: "String".to_string(),
266 })
267 }
268 }
269}
270
271impl TryFrom<Value> for serde_json::Value {
272 type Error = Error;
273
274 fn try_from(value: Value) -> Result<serde_json::Value, Error> {
275 match value {
276 Value::Array(a) => Ok(serde_json::Value::Array(
277 a.into_iter()
278 .map(|v| v.try_into())
279 .collect::<Result<Vec<_>, Error>>()?,
280 )),
281 Value::Bool(b) => Ok(serde_json::Value::Bool(b)),
282 Value::Float64(f) => Ok(serde_json::Value::Number(
283 serde_json::Number::from_f64(f).ok_or_else(|| Error::TypeConversionFailed {
284 src: "Value::Float64".to_string(),
285 dst: "serde_json::Number".to_string(),
286 })?,
287 )),
288 Value::Int64(i) => Ok(serde_json::Value::Number(i.into())),
289 Value::Map(hm) => Ok(serde_json::Value::Object(
290 hm.into_iter()
291 .map(|(k, v)| {
292 let val = v.try_into()?;
293 Ok((k, val))
294 })
295 .collect::<Result<serde_json::Map<String, serde_json::Value>, Error>>()?,
296 )),
297 Value::Null => Ok(serde_json::Value::Null),
298 Value::String(s) => Ok(serde_json::Value::String(s)),
299 Value::UInt64(i) => Ok(serde_json::Value::Number(i.into())),
300 Value::Uuid(uuid) => Ok(serde_json::Value::String(uuid.to_hyphenated().to_string())),
301 }
302 }
303}
304
305impl<T> TryFrom<Value> for Vec<T>
306where
307 T: TryFrom<Value, Error = Error>,
308{
309 type Error = Error;
310
311 fn try_from(value: Value) -> Result<Self, Self::Error> {
312 if let Value::Array(a) = value {
313 if let Some(Value::Null) = a.get(0) {
314 Ok(Vec::new())
316 } else {
317 a.into_iter()
319 .map(|v| v.try_into())
320 .collect::<Result<Vec<_>, Error>>()
321 }
322 } else {
323 Err(Error::TypeConversionFailed {
324 src: format!("{:#?}", value),
325 dst: "<T> where T: TryFrom<Value, Error = Error>".to_string(),
326 })
327 }
328 }
329}
330
331impl TryFrom<Value> for HashMap<String, Value> {
332 type Error = Error;
333
334 fn try_from(value: Value) -> Result<HashMap<String, Value>, Error> {
335 match value {
336 Value::Map(hm) => Ok(hm),
337 _ => Err(Error::TypeConversionFailed {
338 src: format!("{:#?}", value),
339 dst: "HashMap<String, Value>".to_string(),
340 }),
341 }
342 }
343}
344
345#[cfg(test)]
346mod tests {
347 use super::Value;
348
349 #[test]
351 fn test_value_send() {
352 fn assert_send<T: Send>() {}
353 assert_send::<Value>();
354 }
355
356 #[test]
358 fn test_value_sync() {
359 fn assert_sync<T: Sync>() {}
360 assert_sync::<Value>();
361 }
362}