1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use crate::{
	error::{Error::*, LocError, Result},
	throw, ObjValueBuilder, Val,
};
use serde_json::{Map, Number, Value};
use std::convert::{TryFrom, TryInto};

impl TryFrom<&Val> for Value {
	type Error = LocError;
	fn try_from(v: &Val) -> Result<Self> {
		Ok(match v {
			Val::Bool(b) => Self::Bool(*b),
			Val::Null => Self::Null,
			Val::Str(s) => Self::String((s as &str).into()),
			Val::Num(n) => Self::Number(if n.fract() <= f64::EPSILON {
				(*n as i64).into()
			} else {
				Number::from_f64(*n).expect("to json number")
			}),
			Val::Arr(a) => {
				let mut out = Vec::with_capacity(a.len());
				for item in a.iter() {
					out.push((&item?).try_into()?);
				}
				Self::Array(out)
			}
			Val::Obj(o) => {
				let mut out = Map::new();
				for key in o.fields() {
					out.insert(
						(&key as &str).into(),
						(&o.get(key)?.expect("field exists")).try_into()?,
					);
				}
				Self::Object(out)
			}
			Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),
		})
	}
}

impl From<&Value> for Val {
	fn from(v: &Value) -> Self {
		match v {
			Value::Null => Self::Null,
			Value::Bool(v) => Self::Bool(*v),
			Value::Number(n) => Self::Num(n.as_f64().expect("as f64")),
			Value::String(s) => Self::Str((s as &str).into()),
			Value::Array(a) => {
				let mut out: Vec<Self> = Vec::with_capacity(a.len());
				for v in a {
					out.push(v.into());
				}
				Self::Arr(out.into())
			}
			Value::Object(o) => {
				let mut builder = ObjValueBuilder::with_capacity(o.len());
				for (k, v) in o {
					builder.member((k as &str).into()).value(v.into());
				}
				Self::Obj(builder.build())
			}
		}
	}
}