1use crate::{2 Context,3 error::{Error::*, LocError, Result},4 throw, LazyBinding, LazyVal, ObjMember, ObjValue, Val,5};6use jrsonnet_parser::Visibility;7use rustc_hash::FxHasher;8use serde_json::{Map, Number, Value};9use std::{10 collections::HashMap,11 convert::{TryFrom, TryInto},12 hash::BuildHasherDefault,13 rc::Rc,14};1516impl TryFrom<&Val> for Value {17 type Error = LocError;18 fn try_from(v: &Val) -> Result<Self> {19 Ok(match v {20 Val::Bool(b) => Self::Bool(*b),21 Val::Null => Self::Null,22 Val::Str(s) => Self::String((s as &str).into()),23 Val::Num(n) => Self::Number(if n.fract() <= f64::EPSILON {24 (*n as i64).into()25 } else {26 Number::from_f64(*n).expect("to json number")27 }),28 Val::Arr(a) => {29 let mut out = Vec::with_capacity(a.len());30 for item in a.iter() {31 out.push((&item?).try_into()?);32 }33 Self::Array(out)34 }35 Val::Obj(o) => {36 let mut out = Map::new();37 for key in o.fields() {38 out.insert(39 (&key as &str).into(),40 (&o.get(key)?.expect("field exists")).try_into()?,41 );42 }43 Self::Object(out)44 }45 Val::Func(_) => throw!(RuntimeError("tried to manifest function".into())),46 })47 }48}4950impl From<&Value> for Val {51 fn from(v: &Value) -> Self {52 match v {53 Value::Null => Self::Null,54 Value::Bool(v) => Self::Bool(*v),55 Value::Number(n) => Self::Num(n.as_f64().expect("as f64")),56 Value::String(s) => Self::Str((s as &str).into()),57 Value::Array(a) => {58 let mut out = Vec::with_capacity(a.len());59 for v in a {60 out.push(LazyVal::new_resolved(v.into()));61 }62 Self::Arr(out.into())63 }64 Value::Object(o) => {65 let mut entries = HashMap::with_capacity_and_hasher(66 o.len(),67 BuildHasherDefault::<FxHasher>::default(),68 );69 for (k, v) in o {70 entries.insert(71 (k as &str).into(),72 ObjMember {73 add: false,74 visibility: Visibility::Normal,75 invoke: LazyBinding::Bound(LazyVal::new_resolved(v.into())),76 location: None,77 },78 );79 }80 Self::Obj(ObjValue::new(Context::new(), None, Rc::new(entries), Rc::new(Vec::new())))81 }82 }83 }84}