1use std::collections::HashMap;
2use std::convert::{TryFrom, TryInto};
3use std::fmt;
4use std::fmt::Display;
5
6use num_bigint::BigInt;
7use num_traits::{ToPrimitive, Zero};
8use serde::Serialize;
9
10use crate::error::{Error, Result, Unexpected};
11use crate::path::{Path, PathNode};
12use crate::value::ser::ValueSerializer;
13
14mod de;
15mod ser;
16
17#[derive(Debug, Clone, PartialEq)]
18pub enum Value {
19 Nil,
20 Integer(BigInt),
21 Float(f64),
22 Boolean(bool),
23 String(String),
24 Map(HashMap<String, Value>),
25 Array(Vec<Value>),
26}
27
28impl Default for Value {
29 fn default() -> Self {
30 Value::Nil
31 }
32}
33
34impl Display for Value {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 match *self {
37 Value::String(ref value) => write!(f, "{}", value),
38 Value::Boolean(value) => write!(f, "{}", value),
39 Value::Integer(ref value) => write!(f, "{}", value),
40 Value::Float(value) => write!(f, "{}", value),
41 Value::Nil => write!(f, "nil"),
42 Value::Map(ref map) => write!(f, "{:?}", map),
43 Value::Array(ref array) => write!(f, "{:?}", array),
44 }
45 }
46}
47
48impl<T> From<Option<T>> for Value
49where
50 T: Into<Value>,
51{
52 fn from(value: Option<T>) -> Self {
53 match value {
54 Some(value) => value.into(),
55 None => Value::Nil,
56 }
57 }
58}
59
60impl From<String> for Value {
61 fn from(value: String) -> Self {
62 Value::String(value)
63 }
64}
65
66impl<'a> From<&'a str> for Value {
67 fn from(value: &'a str) -> Self {
68 Value::String(value.into())
69 }
70}
71
72macro_rules! impl_from_int_to_value {
73 ($ty:ty) => {
74 impl From<$ty> for Value {
75 fn from(value: $ty) -> Self {
76 Value::Integer(BigInt::from(value))
77 }
78 }
79 };
80}
81
82impl_from_int_to_value!(i8);
83impl_from_int_to_value!(i16);
84impl_from_int_to_value!(i32);
85impl_from_int_to_value!(i64);
86impl_from_int_to_value!(isize);
87
88impl_from_int_to_value!(u8);
89impl_from_int_to_value!(u16);
90impl_from_int_to_value!(u32);
91impl_from_int_to_value!(u64);
92impl_from_int_to_value!(usize);
93
94impl From<f64> for Value {
95 fn from(value: f64) -> Self {
96 Value::Float(value)
97 }
98}
99
100impl From<f32> for Value {
101 fn from(value: f32) -> Self {
102 Value::Float(value as f64)
103 }
104}
105
106impl From<bool> for Value {
107 fn from(value: bool) -> Self {
108 Value::Boolean(value)
109 }
110}
111
112impl<T> From<HashMap<String, T>> for Value
113where
114 T: Into<Value>,
115{
116 fn from(values: HashMap<String, T>) -> Self {
117 let mut r = HashMap::new();
118
119 for (k, v) in values {
120 r.insert(k.clone(), v.into());
121 }
122
123 Value::Map(r)
124 }
125}
126
127impl<T> From<Vec<T>> for Value
128where
129 T: Into<Value>,
130{
131 fn from(values: Vec<T>) -> Self {
132 let mut l = Vec::new();
133
134 for v in values {
135 l.push(v.into());
136 }
137
138 Value::Array(l)
139 }
140}
141
142impl TryFrom<Value> for bool {
143 type Error = Error;
144
145 fn try_from(value: Value) -> Result<Self> {
146 match value {
147 Value::Boolean(value) => Ok(value),
148 Value::Integer(value) => Ok(value.ne(&Zero::zero())),
149 Value::Float(value) => Ok(value != 0.0),
150
151 Value::String(ref value) => {
152 match value.to_lowercase().as_ref() {
153 "1" | "true" | "on" | "yes" => Ok(true),
154 "0" | "false" | "off" | "no" => Ok(false),
155
156 s => Err(Error::invalid_type(Unexpected::Str(s.into()), "a boolean")),
158 }
159 }
160
161 Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a boolean")),
163 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a boolean")),
164 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a boolean")),
165 }
166 }
167}
168
169macro_rules! impl_try_from_value_to_int {
170 ($ty:ty, $ident:ident) => {
171 impl TryFrom<Value> for $ty {
172 type Error = Error;
173
174 fn try_from(value: Value) -> Result<Self> {
175 match value {
176 Value::Integer(value) => match value.$ident() {
177 Some(v) => Ok(v),
178 None => Err(Error::too_large(value)),
179 },
180 Value::String(ref s) => {
181 match s.to_lowercase().as_ref() {
182 "true" | "on" | "yes" => Ok(1),
183 "false" | "off" | "no" => Ok(0),
184 _ => {
185 s.parse().map_err(|_| {
186 Error::invalid_type(Unexpected::Str(s.clone()), "an integer")
188 })
189 }
190 }
191 }
192 Value::Boolean(value) => Ok(if value { 1 } else { 0 }),
193 Value::Float(value) => Ok(value.round() as $ty),
194
195 Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "an integer")),
197 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "an integer")),
198 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "an integer")),
199 }
200 }
201 }
202 };
203}
204
205impl_try_from_value_to_int!(i8, to_i8);
206impl_try_from_value_to_int!(i16, to_i16);
207impl_try_from_value_to_int!(i32, to_i32);
208impl_try_from_value_to_int!(i64, to_i64);
209impl_try_from_value_to_int!(isize, to_isize);
210impl_try_from_value_to_int!(u8, to_u8);
211impl_try_from_value_to_int!(u16, to_u16);
212impl_try_from_value_to_int!(u32, to_u32);
213impl_try_from_value_to_int!(u64, to_u64);
214impl_try_from_value_to_int!(usize, to_usize);
215
216macro_rules! impl_try_from_value_to_float {
217 ($ty:ty, $ident:ident) => {
218 impl TryFrom<Value> for $ty {
219 type Error = Error;
220
221 fn try_from(value: Value) -> Result<Self> {
222 match value {
223 Value::Float(value) => Ok(value as $ty),
224
225 Value::String(ref s) => {
226 match s.to_lowercase().as_ref() {
227 "true" | "on" | "yes" => Ok(1.0),
228 "false" | "off" | "no" => Ok(0.0),
229 _ => {
230 s.parse().map_err(|_| {
231 Error::invalid_type(
233 Unexpected::Str(s.clone()),
234 "a floating point",
235 )
236 })
237 }
238 }
239 }
240
241 Value::Integer(value) => match value.$ident() {
242 Some(v) => Ok(v),
243 None => Err(Error::too_large(value)),
244 },
245 Value::Boolean(value) => Ok(if value { 1.0 } else { 0.0 }),
246
247 Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a floating point")),
249 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a floating point")),
250 Value::Array(_) => {
251 Err(Error::invalid_type(Unexpected::Array, "a floating point"))
252 }
253 }
254 }
255 }
256 };
257}
258
259impl_try_from_value_to_float!(f32, to_f32);
260impl_try_from_value_to_float!(f64, to_f64);
261
262impl TryFrom<Value> for String {
263 type Error = Error;
264
265 fn try_from(value: Value) -> Result<Self> {
266 match value {
267 Value::String(value) => Ok(value),
268
269 Value::Boolean(value) => Ok(value.to_string()),
270 Value::Integer(value) => Ok(value.to_string()),
271 Value::Float(value) => Ok(value.to_string()),
272
273 Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a string")),
275 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a string")),
276 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a string")),
277 }
278 }
279}
280
281impl TryFrom<Value> for Vec<Value> {
282 type Error = Error;
283
284 fn try_from(value: Value) -> Result<Self> {
285 match value {
286 Value::Array(value) => Ok(value),
287
288 Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "an array")),
290 Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "an array")),
291 Value::Integer(value) => {
292 Err(Error::invalid_type(Unexpected::Integer(value), "an array"))
293 }
294 Value::Boolean(value) => Err(Error::invalid_type(Unexpected::Bool(value), "an array")),
295 Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "an array")),
296 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "an array")),
297 }
298 }
299}
300
301impl TryFrom<Value> for HashMap<String, Value> {
302 type Error = Error;
303
304 fn try_from(value: Value) -> Result<Self> {
305 match value {
306 Value::Map(value) => Ok(value),
307
308 Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "a map")),
310 Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a map")),
311 Value::Integer(value) => Err(Error::invalid_type(Unexpected::Integer(value), "a map")),
312 Value::Boolean(value) => Err(Error::invalid_type(Unexpected::Bool(value), "a map")),
313 Value::Nil => Err(Error::invalid_type(Unexpected::Unit, "a map")),
314 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a map")),
315 }
316 }
317}
318
319impl TryFrom<Value> for () {
320 type Error = Error;
321
322 fn try_from(value: Value) -> Result<Self> {
323 Ok(())
324 }
325}
326
327impl Value {
328 pub fn merge(&mut self, source: Value) -> Result<()> {
329 match self {
330 Value::Boolean(v_t) => match source {
331 Value::Boolean(v_s) => {
332 *v_t = v_s;
333 Ok(())
334 }
335
336 Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "a bool")),
338 Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a bool")),
339 Value::Integer(value) => {
340 Err(Error::invalid_type(Unexpected::Integer(value), "a bool"))
341 }
342 Value::Nil => Ok(()),
343 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a bool")),
344 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a bool")),
345 },
346 Value::Integer(v_t) => match source {
347 Value::Integer(v_s) => {
348 *v_t = v_s;
349 Ok(())
350 }
351
352 Value::Float(value) => {
354 Err(Error::invalid_type(Unexpected::Float(value), "a integer"))
355 }
356 Value::String(value) => {
357 Err(Error::invalid_type(Unexpected::Str(value), "a integer"))
358 }
359 Value::Boolean(value) => {
360 Err(Error::invalid_type(Unexpected::Bool(value), "a integer"))
361 }
362 Value::Nil => Ok(()),
363 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a integer")),
364 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a integer")),
365 },
366 Value::Float(v_t) => match source {
367 Value::Float(v_s) => {
368 *v_t = v_s;
369 Ok(())
370 }
371
372 Value::Integer(value) => {
374 Err(Error::invalid_type(Unexpected::Integer(value), "a float"))
375 }
376 Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a float")),
377 Value::Boolean(value) => {
378 Err(Error::invalid_type(Unexpected::Bool(value), "a float"))
379 }
380 Value::Nil => Ok(()),
381 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a float")),
382 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a float")),
383 },
384 Value::String(v_t) => match source {
385 Value::String(v_s) => {
386 *v_t = v_s;
387 Ok(())
388 }
389
390 Value::Integer(value) => {
392 Err(Error::invalid_type(Unexpected::Integer(value), "a string"))
393 }
394 Value::Float(value) => {
395 Err(Error::invalid_type(Unexpected::Float(value), "a string"))
396 }
397 Value::Boolean(value) => {
398 Err(Error::invalid_type(Unexpected::Bool(value), "a string"))
399 }
400 Value::Nil => Ok(()),
401 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a string")),
402 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a string")),
403 },
404 Value::Nil => match source {
405 Value::Nil => Ok(()),
406 _ => {
407 *self = source;
408 Ok(())
409 }
410 },
411 Value::Map(v_t) => match source {
412 Value::Map(v_s) => {
413 for (k, v) in v_s {
414 match v_t.get_mut(&k) {
415 Some(j) => Value::merge(j, v)?,
416 None => {
417 v_t.insert(k, v);
418 }
419 }
420 }
421 Ok(())
422 }
423 Value::Integer(value) => {
425 Err(Error::invalid_type(Unexpected::Integer(value), "a map"))
426 }
427 Value::Float(value) => Err(Error::invalid_type(Unexpected::Float(value), "a map")),
428 Value::Boolean(value) => Err(Error::invalid_type(Unexpected::Bool(value), "a map")),
429 Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a map")),
430 Value::Nil => Ok(()),
431 Value::Array(_) => Err(Error::invalid_type(Unexpected::Array, "a map")),
432 },
433 Value::Array(v_t) => match source {
434 Value::Array(v_s) => {
435 for (index, v) in v_s.into_iter().enumerate() {
436 match v_t.get_mut(index) {
437 Some(j) => Value::merge(j, v)?,
438 None => {
439 v_t.push(v);
440 }
441 }
442 }
443 Ok(())
444 }
445 Value::Integer(value) => {
447 Err(Error::invalid_type(Unexpected::Integer(value), "a array"))
448 }
449 Value::Float(value) => {
450 Err(Error::invalid_type(Unexpected::Float(value), "a array"))
451 }
452 Value::Boolean(value) => {
453 Err(Error::invalid_type(Unexpected::Bool(value), "a array"))
454 }
455 Value::String(value) => Err(Error::invalid_type(Unexpected::Str(value), "a array")),
456 Value::Nil => Ok(()),
457 Value::Map(_) => Err(Error::invalid_type(Unexpected::Map, "a array")),
458 },
459 }
460 }
461
462 pub fn set<P, IntoValue, IntoErr>(
463 &mut self,
464 path: P,
465 input_value: IntoValue,
466 ) -> Result<Value, Error>
467 where
468 P: TryInto<Path, Error = IntoErr>,
469 IntoValue: Into<Value>,
470 IntoErr: Into<Error>,
471 {
472 let input_value = input_value.into();
473 let path = path.try_into().map_err(|err| err.into())?;
474 unsafe {
475 let mut parent = self as *mut Value;
476 let mut target = self as *mut Value;
477 let v = vec![1];
478 for sub_path in path.iter() {
479 match *sub_path {
480 PathNode::Identifier(ref ident) => match &mut *parent {
481 Value::Map(parent_map) => {
482 target = parent_map.entry(ident.clone()).or_default();
483 parent = target;
484 }
485
486 _ => {
487 *parent = HashMap::<String, Value>::new().into();
488 if let Value::Map(parent_map) = &mut *parent {
489 target = parent_map.entry(ident.clone()).or_default();
490 parent = target;
491 } else {
492 unreachable!()
493 }
494 }
495 },
496 PathNode::Index(index) => match &mut *parent {
497 Value::Array(parent_array) => {
498 target = Value::get_array_slot(parent_array, index);
499 parent = target;
500 }
501
502 _ => {
503 *parent = vec![Value::default()].into();
504 if let Value::Array(parent_array) = &mut *parent {
505 target = Value::get_array_slot(parent_array, index);
506 parent = target;
507 } else {
508 unreachable!()
509 }
510 }
511 },
512 }
513 }
514
515 let result = (*target).clone();
516 *target = input_value;
517 Ok(result)
518 }
519 }
520
521 pub fn get<T, P, IntoErr>(&self, path: P) -> Result<Option<T>, Error>
522 where
523 T: std::convert::TryFrom<Value, Error = IntoErr>,
524 P: TryInto<Path, Error = IntoErr>,
525 IntoErr: Into<Error>,
526 {
527 let path = path.try_into().map_err(|err| err.into())?;
528 let value = path
529 .iter()
530 .scan(self, |value, child_path| {
531 let result = match *child_path {
532 PathNode::Identifier(ref id) => match **value {
533 Value::Map(ref map) => map.get(id),
534 _ => None,
535 },
536
537 PathNode::Index(index) => match **value {
538 Value::Array(ref array) => {
539 let index = Value::map_index(index, array.len());
540
541 if index >= array.len() {
542 None
543 } else {
544 Some(&array[index])
545 }
546 }
547 _ => None,
548 },
549 };
550 if let Some(v) = result {
551 *value = v;
552 }
553 result
554 })
555 .last();
556 match value {
557 None => Ok(None),
558 Some(value) => Ok(Some(
559 Value::try_into(value.clone()).map_err(|err: IntoErr| err.into())?,
560 )),
561 }
562 }
563
564 fn map_index(index: isize, len: usize) -> usize {
565 if index >= 0 {
566 index as usize
567 } else {
568 len - (index.abs() as usize)
569 }
570 }
571
572 unsafe fn get_array_slot(array: &mut Vec<Value>, index: isize) -> *mut Value {
573 let index = Value::map_index(index, array.len());
574 match array.get_mut(index) {
575 Some(v) => v,
576 None => {
577 array.insert(index, Value::default());
578 match array.get_mut(index) {
579 Some(v) => v,
580 None => unreachable!(),
581 }
582 }
583 }
584 }
585}
586
587pub fn to_value<T>(from: T) -> Result<Value>
588where
589 T: Serialize,
590{
591 let mut serializer = ValueSerializer::default();
592 from.serialize(&mut serializer)?;
593 Ok(serializer.output)
594}