difftreelog
feat std.parseYaml intrinsic
in: master
6 files changed
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth1[package]2name = "jrsonnet-evaluator"3description = "jsonnet interpreter"4version = "0.4.2"5authors = ["Yaroslav Bolyukin <iam@lach.pw>"]6license = "MIT"7edition = "2018"89[features]10default = ["serialized-stdlib", "explaining-traces", "serde-json"]11# Serializes standard library AST instead of parsing them every run12serialized-stdlib = ["serde", "bincode", "jrsonnet-parser/deserialize"]13# Allow to convert Val into serde_json::Value and backwards14serde-json = ["serde", "serde_json"]15# Rustc-like trace visualization16explaining-traces = ["annotate-snippets"]17# Allows library authors to throw custom errors18anyhow-error = ["anyhow"]1920# Unlocks extra features, but works only on unstable21unstable = []2223[dependencies]24jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }25jrsonnet-parser = { path = "../jrsonnet-parser", version = "0.4.2" }26jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }27jrsonnet-types = { path = "../jrsonnet-types", version = "0.4.2" }28pathdiff = "0.2.0"2930md5 = "0.7.0"31base64 = "0.13.0"32rustc-hash = "1.1.0"3334thiserror = "1.0"35gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }3637[dependencies.anyhow]38version = "1.0"39optional = true4041# Serialized stdlib42[dependencies.serde]43version = "1.0"44optional = true45[dependencies.bincode]46version = "1.3.1"47optional = true4849# Serde json50[dependencies.serde_json]51version = "1.0"52optional = true5354# Explaining traces55[dependencies.annotate-snippets]56version = "0.9.1"57features = ["color"]58optional = true5960[build-dependencies]61jrsonnet-parser = { path = "../jrsonnet-parser", features = [62 "serialize",63 "deserialize",64], version = "0.4.2" }65jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }66serde = "1.0"67bincode = "1.3.1"1[package]2name = "jrsonnet-evaluator"3description = "jsonnet interpreter"4version = "0.4.2"5authors = ["Yaroslav Bolyukin <iam@lach.pw>"]6license = "MIT"7edition = "2018"89[features]10default = ["serialized-stdlib", "explaining-traces"]11# Serializes standard library AST instead of parsing them every run12serialized-stdlib = ["bincode", "jrsonnet-parser/deserialize"]13# Rustc-like trace visualization14explaining-traces = ["annotate-snippets"]15# Allows library authors to throw custom errors16anyhow-error = ["anyhow"]1718# Unlocks extra features, but works only on unstable19unstable = []2021[dependencies]22jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }23jrsonnet-parser = { path = "../jrsonnet-parser", version = "0.4.2" }24jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }25jrsonnet-types = { path = "../jrsonnet-types", version = "0.4.2" }26pathdiff = "0.2.0"2728md5 = "0.7.0"29base64 = "0.13.0"30rustc-hash = "1.1.0"3132thiserror = "1.0"33gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }3435serde = "1.0"36serde_json = "1.0"37serde_yaml = { git = "https://github.com/CertainLach/serde-yaml", branch = "feature/old-octals-quirk" }3839[dependencies.anyhow]40version = "1.0"41optional = true4243# Serialized stdlib44[dependencies.bincode]45version = "1.3.1"46optional = true4748# Explaining traces49[dependencies.annotate-snippets]50version = "0.9.1"51features = ["color"]52optional = true5354[build-dependencies]55jrsonnet-parser = { path = "../jrsonnet-parser", features = [56 "serialize",57 "deserialize",58], version = "0.4.2" }59jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }60serde = "1.0"61bincode = "1.3.1"crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -3,15 +3,17 @@
equals,
error::{Error::*, Result},
operator::evaluate_mod_op,
- parse_args, primitive_equals, push_frame, throw, with_state, ArrValue, Context,
- EvaluationState, FuncVal, IndexableVal, LazyVal, Val,
+ parse_args, primitive_equals, push_frame, throw, with_state, ArrValue, Context, FuncVal,
+ IndexableVal, LazyVal, Val,
};
use format::{format_arr, format_obj};
use gcmodule::Cc;
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ArgsDesc, ExprLocation};
use jrsonnet_types::ty;
-use std::{collections::HashMap, path::PathBuf, rc::Rc};
+use serde::Deserialize;
+use serde_yaml::DeserializingQuirks;
+use std::{collections::HashMap, convert::TryFrom, path::PathBuf, rc::Rc};
pub mod stdlib;
pub use stdlib::*;
@@ -128,6 +130,7 @@
("strReplace".into(), builtin_str_replace),
("splitLimit".into(), builtin_splitlimit),
("parseJson".into(), builtin_parse_json),
+ ("parseYaml".into(), builtin_parse_yaml),
("asciiUpper".into(), builtin_ascii_upper),
("asciiLower".into(), builtin_ascii_lower),
("member".into(), builtin_member),
@@ -210,9 +213,30 @@
parse_args!(context, "parseJson", args, 1, [
0, s: ty!(string) => Val::Str;
], {
- let state = EvaluationState::default();
- let path = PathBuf::from("std.parseJson").into();
- state.evaluate_snippet_raw(path ,s)
+ let value: serde_json::Value = serde_json::from_str(&s).map_err(|e| RuntimeError(format!("failed to parse json: {}", e).into()))?;
+ Ok(Val::try_from(&value)?)
+ })
+}
+
+fn builtin_parse_yaml(context: Context, _loc: &ExprLocation, args: &ArgsDesc) -> Result<Val> {
+ parse_args!(context, "parseYaml", args, 1, [
+ 0, s: ty!(string) => Val::Str;
+ ], {
+ let value = serde_yaml::Deserializer::from_str_with_quirks(&s, DeserializingQuirks { old_octals: true });
+ let mut out = vec![];
+ for item in value {
+ let value = serde_json::Value::deserialize(item)
+ .map_err(|e| RuntimeError(format!("failed to parse yaml: {}", e).into()))?;
+ let val = Val::try_from(&value)?;
+ out.push(val);
+ }
+ if out.is_empty() {
+ Ok(Val::Null)
+ } else if out.len() == 1 {
+ Ok(out.into_iter().next().unwrap())
+ } else {
+ Ok(Val::Arr(out.into()))
+ }
})
}
crates/jrsonnet-evaluator/src/integrations/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/integrations/mod.rs
+++ b/crates/jrsonnet-evaluator/src/integrations/mod.rs
@@ -1,2 +1 @@
-#[cfg(feature = "serde-json")]
pub mod serde;
crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/integrations/serde.rs
+++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs
@@ -15,7 +15,7 @@
Val::Num(n) => Self::Number(if n.fract() <= f64::EPSILON {
(*n as i64).into()
} else {
- Number::from_f64(*n).expect("to json number")
+ Number::from_f64(*n).expect("jsonnet numbers can't be infinite or NaN")
}),
Val::Arr(a) => {
let mut out = Vec::with_capacity(a.len());
@@ -29,7 +29,9 @@
for key in o.fields() {
out.insert(
(&key as &str).into(),
- (&o.get(key)?.expect("field exists")).try_into()?,
+ (&o.get(key)?
+ .expect("key is present in fields, so value should exist"))
+ .try_into()?,
);
}
Self::Object(out)
@@ -39,27 +41,30 @@
}
}
-impl From<&Value> for Val {
- fn from(v: &Value) -> Self {
- match v {
+impl TryFrom<&Value> for Val {
+ type Error = LocError;
+ fn try_from(v: &Value) -> Result<Self> {
+ Ok(match v {
Value::Null => Self::Null,
Value::Bool(v) => Self::Bool(*v),
- Value::Number(n) => Self::Num(n.as_f64().expect("as f64")),
+ Value::Number(n) => Self::Num(n.as_f64().ok_or_else(|| {
+ RuntimeError(format!("json number can't be represented as jsonnet: {}", n).into())
+ })?),
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());
+ out.push(v.try_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());
+ builder.member((k as &str).into()).value(v.try_into()?);
}
Self::Obj(builder.build())
}
- }
+ })
}
}
crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -98,7 +98,7 @@
let mut n = self.resolver.resolve(path);
let mut offset = error.location.offset;
let is_eof = if offset >= source_code.len() {
- offset = source_code.len() - 1;
+ offset = source_code.len().saturating_sub(1);
true
} else {
false
crates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/std.jsonnet
+++ b/crates/jrsonnet-stdlib/src/std.jsonnet
@@ -23,6 +23,7 @@
trace:: $intrinsic(trace),
id:: $intrinsic(id),
parseJson:: $intrinsic(parseJson),
+ parseYaml:: $intrinsic(parseYaml),
log:: $intrinsic(log),
pow:: $intrinsic(pow),