git.delta.rocks / jrsonnet / refs/commits / 7b8b823d230b

difftreelog

refactor! implement serde support directly

Yaroslav Bolyukin2022-10-25parent: #2e5acc0.patch.diff
in: master
Instead of relying on `serde_json::Value`.

BREAKING CHANGE: There is no longer `impl Typed for serde_json::Value`,
either parse directly into jrsonnet-evaluator, or use `serde_transcode`

9 files changed

added.envrcdiffbeforeafterboth

no changes

modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
13# Experimental feature, which allows to preserve order of object fields13# Experimental feature, which allows to preserve order of object fields
14exp-preserve-order = [14exp-preserve-order = [
15 "jrsonnet-evaluator/exp-preserve-order",15 "jrsonnet-evaluator/exp-preserve-order",
16 "jrsonnet-evaluator/exp-serde-preserve-order",
17 "jrsonnet-cli/exp-preserve-order",16 "jrsonnet-cli/exp-preserve-order",
18 "jrsonnet-cli/exp-serde-preserve-order",
19]17]
20# Destructuring of locals18# Destructuring of locals
21exp-destruct = ["jrsonnet-evaluator/exp-destruct"]19exp-destruct = ["jrsonnet-evaluator/exp-destruct"]
modifiedcrates/jrsonnet-cli/Cargo.tomldiffbeforeafterboth
11 "jrsonnet-evaluator/exp-preserve-order",11 "jrsonnet-evaluator/exp-preserve-order",
12 "jrsonnet-stdlib/exp-preserve-order",12 "jrsonnet-stdlib/exp-preserve-order",
13]13]
14exp-serde-preserve-order = [
15 "jrsonnet-evaluator/exp-serde-preserve-order",
16 "jrsonnet-stdlib/exp-serde-preserve-order",
17]
18legacy-this-file = ["jrsonnet-stdlib/legacy-this-file"]14legacy-this-file = ["jrsonnet-stdlib/legacy-this-file"]
1915
20[dependencies]16[dependencies]
modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
1818
19# Allows to preserve field order in objects19# Allows to preserve field order in objects
20exp-preserve-order = []20exp-preserve-order = []
21exp-serde-preserve-order = ["serde_json/preserve_order"]
22# Implements field destructuring21# Implements field destructuring
23exp-destruct = ["jrsonnet-parser/exp-destruct"]22exp-destruct = ["jrsonnet-parser/exp-destruct"]
24# Provide Typed for conversions to/from serde_json::Value type23# Provide Typed for conversions to/from serde_json::Value type
40thiserror = "1.0"39thiserror = "1.0"
4140
42serde = "1.0"41serde = "1.0"
43# Optional integration
44serde_json = { version = "1.0.82", optional = true }
4542
46anyhow = { version = "1.0", optional = true }43anyhow = { version = "1.0", optional = true }
47# Friendly errors44# Friendly errors
modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
1use jrsonnet_types::ComplexValType;1use std::borrow::Cow;
2
3use jrsonnet_gcmodule::Cc;
2use serde_json::{Map, Number, Value};4use serde::{de::Visitor, ser::Error, Deserialize, Serialize};
35
4use crate::{6use crate::{error::Result, val::ArrValue, ObjValueBuilder, State, Val};
5 error::{Error::*, Result},7
6 throw,8impl<'de> Deserialize<'de> for Val {
7 typed::Typed,9 fn deserialize<D>(deserializer: D) -> Result<Val, D::Error>
8 ObjValueBuilder, State, Val,10 where
9};11 D: serde::Deserializer<'de>,
12 {
13 struct ValVisitor;
14
15 // macro_rules! visit_num {
16 // ($($method:ident => $ty:ty),* $(,)?) => {$(
17 // fn $method<E>(self, v: $ty) -> Result<Self::Value, E>
18 // where
19 // E: serde::de::Error,
20 // {
21 // Ok(Val::Num(f64::from(v)))
22 // }
23 // )*};
24 // }
25
26 impl<'de> Visitor<'de> for ValVisitor {
27 type Value = Val;
28
29 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
30 where
31 E: serde::de::Error,
32 {
33 Ok(Val::Bool(v))
34 }
35 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
36 where
37 E: serde::de::Error,
38 {
39 if !v.is_finite() {
40 return Err(E::custom("only finite numbers are supported"));
41 }
42 Ok(Val::Num(v))
43 }
44 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
45 where
46 E: serde::de::Error,
47 {
48 Ok(Val::Str(v.into()))
49 }
50
51 // visit_num! {
52 // visit_i8 => i8,
53 // visit_i16 => i16,
54 // visit_i32 => i32,
55 // visit_u8 => u8,
56 // visit_u16 => u16,
57 // visit_u32 => u32,
58 // }
59 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
60 where
61 E: serde::de::Error,
62 {
63 Ok(Val::Num(v as f64))
64 }
65 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
66 where
67 E: serde::de::Error,
68 {
69 Ok(Val::Num(v as f64))
70 }
71
72 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
73 where
74 E: serde::de::Error,
75 {
76 Ok(Val::Arr(ArrValue::Bytes(v.into())))
77 }
78
79 fn visit_none<E>(self) -> Result<Self::Value, E>
80 where
81 E: serde::de::Error,
82 {
83 Ok(Val::Null)
84 }
85 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
86 where
87 D: serde::Deserializer<'de>,
88 {
89 deserializer.deserialize_any(self)
90 }
91
92 fn visit_unit<E>(self) -> Result<Self::Value, E>
93 where
94 E: serde::de::Error,
95 {
96 Ok(Val::Null)
97 }
98
99 fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
100 where
101 D: serde::Deserializer<'de>,
102 {
103 deserializer.deserialize_any(self)
104 }
105
106 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
107 where
108 A: serde::de::SeqAccess<'de>,
109 {
110 let mut out = seq.size_hint().map_or_else(Vec::new, Vec::with_capacity);
111
112 while let Some(val) = seq.next_element::<Val>()? {
113 out.push(val);
114 }
115
116 Ok(Val::Arr(ArrValue::Eager(Cc::new(out))))
117 }
118
119 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
120 where
121 A: serde::de::MapAccess<'de>,
122 {
123 let mut out = map
124 .size_hint()
125 .map_or_else(ObjValueBuilder::new, ObjValueBuilder::with_capacity);
126
127 while let Some((k, v)) = map.next_entry::<Cow<'de, str>, Val>()? {
128 // Jsonnet ignores duplicate keys
129 out.member(k.into()).value_unchecked(v);
130 }
131
132 Ok(Val::Obj(out.build()))
133 }
134
135 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 write!(formatter, "any valid jsonnet value")
137 }
138 }
139 deserializer.deserialize_any(ValVisitor)
140 }
141}
10142
11impl Typed for Value {143impl Serialize for Val {
12 const TYPE: &'static ComplexValType = &ComplexValType::Any;
13
14 fn into_untyped(value: Self, s: State) -> Result<Val> {
15 Ok(match value {
16 Self::Null => Val::Null,
17 Self::Bool(v) => Val::Bool(v),
18 Self::Number(n) => Val::Num(n.as_f64().ok_or_else(|| {
19 RuntimeError(format!("json number can't be represented as jsonnet: {n}").into())
20 })?),
21 Self::String(s) => Val::Str((&s as &str).into()),
22 Self::Array(a) => {
23 let mut out: Vec<Val> = Vec::with_capacity(a.len());
24 for v in a {
25 out.push(Self::into_untyped(v, s.clone())?);
26 }
27 Val::Arr(out.into())
28 }
29 Self::Object(o) => {
30 let mut builder = ObjValueBuilder::with_capacity(o.len());
31 for (k, v) in o {
32 builder
33 .member((&k as &str).into())
34 .value(s.clone(), Self::into_untyped(v, s.clone())?)?;
35 }
36 Val::Obj(builder.build())
37 }
38 })
39 }
40
41 fn from_untyped(value: Val, s: State) -> Result<Self> {144 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
145 where
146 S: serde::Serializer,
147 {
42 Ok(match value {148 match self {
43 Val::Bool(b) => Self::Bool(b),149 Val::Bool(v) => serializer.serialize_bool(*v),
44 Val::Null => Self::Null,150 Val::Null => serializer.serialize_none(),
45 Val::Str(s) => Self::String((&s as &str).into()),151 Val::Str(s) => serializer.serialize_str(s),
46 Val::Num(n) => Self::Number(if n.fract() <= f64::EPSILON {152 Val::Num(n) => serializer.serialize_f64(*n),
47 (n as i64).into()
48 } else {
49 Number::from_f64(n).expect("jsonnet numbers can't be infinite or NaN")
50 }),
51 Val::Arr(a) => {153 Val::Arr(arr) => {
52 let mut out = Vec::with_capacity(a.len());154 let mut seq = serializer.serialize_seq(Some(arr.len()))?;
53 for item in a.iter(s.clone()) {155 for element in arr.iter(State::default()) {
54 out.push(Self::from_untyped(item?, s.clone())?);156 // seq.serialize_element()
55 }157 }
56 Self::Array(out)158 todo!()
57 }159 }
58 Val::Obj(o) => {160 Val::Obj(_) => todo!(),
59 let mut out = Map::new();
60 for key in o.fields(
61 #[cfg(feature = "exp-preserve-order")]
62 cfg!(feature = "exp-serde-preserve-order"),
63 ) {
64 out.insert(
65 (&key as &str).into(),
66 Self::from_untyped(
67 o.get(s.clone(), key)?
68 .expect("key is present in fields, so value should exist"),
69 s.clone(),
70 )?,
71 );
72 }
73 Self::Object(out)
74 }
75 Val::Func(_) => throw!("tried to manifest function"),161 Val::Func(_) => Err(S::Error::custom("tried to manifest function")),
76 })162 }
77 }163 }
78}164}
79165
modifiedcrates/jrsonnet-stdlib/Cargo.tomldiffbeforeafterboth
15legacy-this-file = []15legacy-this-file = []
16# Add order preservation flag to some functions16# Add order preservation flag to some functions
17exp-preserve-order = ["jrsonnet-evaluator/exp-preserve-order"]17exp-preserve-order = ["jrsonnet-evaluator/exp-preserve-order"]
18# Preserve order for files parsed via `std.parseJson`
19# Shame it isn't possible to enable per parse call, instead of globally
20exp-serde-preserve-order = [
21 "serde_json/preserve_order",
22 "jrsonnet-evaluator/exp-serde-preserve-order",
23]
2418
25[dependencies]19[dependencies]
26jrsonnet-evaluator = { path = "../jrsonnet-evaluator", features = [20jrsonnet-evaluator = { path = "../jrsonnet-evaluator", version = "0.4.2" }
27 # std.parseJson parses file via serde, then converts Value to evaluator Val
28 "serde_json",
29], version = "0.4.2" }
30jrsonnet-macros = { path = "../jrsonnet-macros", version = "0.4.2" }21jrsonnet-macros = { path = "../jrsonnet-macros", version = "0.4.2" }
31jrsonnet-parser = { path = "../jrsonnet-parser", version = "0.4.2" }22jrsonnet-parser = { path = "../jrsonnet-parser", version = "0.4.2" }
32jrsonnet-gcmodule = "0.3.4"23jrsonnet-gcmodule = "0.3.4"
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
66
7use jrsonnet_evaluator::{7use jrsonnet_evaluator::{
8 error::{Error::*, Result},8 error::{Error::*, Result},
9 function::{builtin::Builtin, ArgLike, CallLocation, FuncVal, TlaArg},9 function::{builtin::Builtin, CallLocation, FuncVal, TlaArg},
10 gc::{GcHashMap, TraceBox},10 gc::{GcHashMap, TraceBox},
11 tb, throw,11 tb,
12 trace::PathResolver,12 trace::PathResolver,
13 typed::{Any, Either, Either2, Either4, VecVal, M1},
14 val::{equals, ArrValue},
15 Context, ContextBuilder, IStr, ObjValue, ObjValueBuilder, State, Thunk, Val,13 Context, ContextBuilder, IStr, ObjValue, ObjValueBuilder, State, Thunk, Val,
16};14};
17use jrsonnet_gcmodule::Cc;15use jrsonnet_gcmodule::Cc;
18use jrsonnet_macros::builtin;
19use jrsonnet_parser::Source;16use jrsonnet_parser::Source;
2017
21mod expr;18mod expr;
modifiedcrates/jrsonnet-stdlib/src/parse.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{
2 error::{Error::RuntimeError, Result},2 error::{Error::RuntimeError, Result},
3 function::builtin,3 function::builtin,
4 typed::{Any, Typed},4 typed::Any,
5 IStr, State, Val,5 IStr, Val,
6};6};
7use serde::Deserialize;7use serde::Deserialize;
88
9#[builtin]9#[builtin]
10pub fn builtin_parse_json(st: State, s: IStr) -> Result<Any> {10pub fn builtin_parse_json(s: IStr) -> Result<Any> {
11 use serde_json::Value;
12 let value: Value = serde_json::from_str(&s)11 let value: Val = serde_json::from_str(&s)
13 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;12 .map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;
14 Ok(Any(Value::into_untyped(value, st)?))13 Ok(Any(value))
15}14}
1615
17#[builtin]16#[builtin]
18pub fn builtin_parse_yaml(st: State, s: IStr) -> Result<Any> {17pub fn builtin_parse_yaml(s: IStr) -> Result<Any> {
19 use serde_json::Value;
20 use serde_yaml_with_quirks::DeserializingQuirks;18 use serde_yaml_with_quirks::DeserializingQuirks;
21 let value = serde_yaml_with_quirks::Deserializer::from_str_with_quirks(19 let value = serde_yaml_with_quirks::Deserializer::from_str_with_quirks(
22 &s,20 &s,
23 DeserializingQuirks { old_octals: true },21 DeserializingQuirks { old_octals: true },
24 );22 );
25 let mut out = vec![];23 let mut out = vec![];
26 for item in value {24 for item in value {
27 let value = Value::deserialize(item)25 let val = Val::deserialize(item)
28 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;26 .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;
29 let val = Value::into_untyped(value, st.clone())?;
30 out.push(val);27 out.push(val);
31 }28 }
32 Ok(Any(if out.is_empty() {29 Ok(Any(if out.is_empty() {
addedflake.nixdiffbeforeafterboth

no changes