git.delta.rocks / jrsonnet / refs/commits / 96da6f397b93

difftreelog

refactor rework layout and path handling

Yaroslav Bolyukin2022-05-26parent: #0374cd0.patch.diff
in: master

32 files changed

modifiedbindings/jsonnet/src/import.rsdiffbeforeafterboth
10 os::raw::{c_char, c_int},10 os::raw::{c_char, c_int},
11 path::{Path, PathBuf},11 path::{Path, PathBuf},
12 ptr::null_mut,12 ptr::null_mut,
13 rc::Rc,
14};13};
1514
16use jrsonnet_evaluator::{15use jrsonnet_evaluator::{
33 out: RefCell<HashMap<PathBuf, Vec<u8>>>,32 out: RefCell<HashMap<PathBuf, Vec<u8>>>,
34}33}
35impl ImportResolver for CallbackImportResolver {34impl ImportResolver for CallbackImportResolver {
36 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {35 fn resolve_file(&self, from: &Path, path: &Path) -> Result<PathBuf> {
37 let base = CString::new(from.to_str().unwrap()).unwrap().into_raw();36 let base = CString::new(from.to_str().unwrap()).unwrap().into_raw();
38 let rel = CString::new(path.to_str().unwrap()).unwrap().into_raw();37 let rel = CString::new(path.to_str().unwrap()).unwrap().into_raw();
39 let found_here: *mut c_char = null_mut();38 let found_here: *mut c_char = null_mut();
73 unsafe { CString::from_raw(result_ptr) };72 unsafe { CString::from_raw(result_ptr) };
74 }73 }
7574
76 Ok(found_here_buf.into())75 Ok(found_here_buf)
77 }76 }
78 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>> {77 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>> {
79 Ok(self.out.borrow().get(resolved).unwrap().clone())78 Ok(self.out.borrow().get(resolved).unwrap().clone())
109 }108 }
110}109}
111impl ImportResolver for NativeImportResolver {110impl ImportResolver for NativeImportResolver {
112 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {111 fn resolve_file(&self, from: &Path, path: &Path) -> Result<PathBuf> {
113 let mut new_path = from.to_owned();112 let mut new_path = from.to_owned();
114 new_path.push(path);113 new_path.push(path);
115 if new_path.exists() {114 if new_path.exists() {
modifiedbindings/jsonnet/src/lib.rsdiffbeforeafterboth
111) -> *const c_char {111) -> *const c_char {
112 let filename = CStr::from_ptr(filename);112 let filename = CStr::from_ptr(filename);
113 match vm113 match vm
114 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))114 .import(PathBuf::from(filename.to_str().unwrap()))
115 .and_then(|v| vm.with_tla(v))115 .and_then(|v| vm.with_tla(v))
116 .and_then(|v| vm.manifest(v))116 .and_then(|v| vm.manifest(v))
117 {117 {
140 let filename = CStr::from_ptr(filename);140 let filename = CStr::from_ptr(filename);
141 let snippet = CStr::from_ptr(snippet);141 let snippet = CStr::from_ptr(snippet);
142 match vm142 match vm
143 .evaluate_snippet_raw(143 .evaluate_snippet(
144 PathBuf::from(filename.to_str().unwrap()).into(),144 filename.to_str().unwrap().into(),
145 snippet.to_str().unwrap().into(),145 snippet.to_str().unwrap().into(),
146 )146 )
147 .and_then(|v| vm.with_tla(v))147 .and_then(|v| vm.with_tla(v))
185) -> *const c_char {185) -> *const c_char {
186 let filename = CStr::from_ptr(filename);186 let filename = CStr::from_ptr(filename);
187 match vm187 match vm
188 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))188 .import(PathBuf::from(filename.to_str().unwrap()))
189 .and_then(|v| vm.with_tla(v))189 .and_then(|v| vm.with_tla(v))
190 .and_then(|v| vm.manifest_multi(v))190 .and_then(|v| vm.manifest_multi(v))
191 {191 {
212 let filename = CStr::from_ptr(filename);212 let filename = CStr::from_ptr(filename);
213 let snippet = CStr::from_ptr(snippet);213 let snippet = CStr::from_ptr(snippet);
214 match vm214 match vm
215 .evaluate_snippet_raw(215 .evaluate_snippet(
216 PathBuf::from(filename.to_str().unwrap()).into(),216 filename.to_str().unwrap().into(),
217 snippet.to_str().unwrap().into(),217 snippet.to_str().unwrap().into(),
218 )218 )
219 .and_then(|v| vm.with_tla(v))219 .and_then(|v| vm.with_tla(v))
255) -> *const c_char {255) -> *const c_char {
256 let filename = CStr::from_ptr(filename);256 let filename = CStr::from_ptr(filename);
257 match vm257 match vm
258 .evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))258 .import(PathBuf::from(filename.to_str().unwrap()))
259 .and_then(|v| vm.with_tla(v))259 .and_then(|v| vm.with_tla(v))
260 .and_then(|v| vm.manifest_stream(v))260 .and_then(|v| vm.manifest_stream(v))
261 {261 {
282 let filename = CStr::from_ptr(filename);282 let filename = CStr::from_ptr(filename);
283 let snippet = CStr::from_ptr(snippet);283 let snippet = CStr::from_ptr(snippet);
284 match vm284 match vm
285 .evaluate_snippet_raw(285 .evaluate_snippet(
286 PathBuf::from(filename.to_str().unwrap()).into(),286 filename.to_str().unwrap().into(),
287 snippet.to_str().unwrap().into(),287 snippet.to_str().unwrap().into(),
288 )288 )
289 .and_then(|v| vm.with_tla(v))289 .and_then(|v| vm.with_tla(v))
modifiedbindings/jsonnet/src/native.rsdiffbeforeafterboth
1use std::{1use std::{
2 ffi::{c_void, CStr},2 ffi::{c_void, CStr},
3 os::raw::{c_char, c_int},3 os::raw::{c_char, c_int},
4 path::Path,
5 rc::Rc,
6};4};
75
8use gcmodule::Cc;6use gcmodule::Cc;
28 cb: JsonnetNativeCallback,26 cb: JsonnetNativeCallback,
29}27}
30impl NativeCallbackHandler for JsonnetNativeCallbackHandler {28impl NativeCallbackHandler for JsonnetNativeCallbackHandler {
31 fn call(&self, s: State, _from: Option<Rc<Path>>, args: &[Val]) -> Result<Val, LocError> {29 fn call(&self, s: State, args: &[Val]) -> Result<Val, LocError> {
32 let mut n_args = Vec::new();30 let mut n_args = Vec::new();
33 for a in args {31 for a in args {
34 n_args.push(Some(Box::new(a.clone())));32 n_args.push(Some(Box::new(a.clone())));
modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
120 opts.manifest.configure(s)?;120 opts.manifest.configure(s)?;
121121
122 let val = if opts.input.exec {122 let val = if opts.input.exec {
123 s.evaluate_snippet_raw(123 s.evaluate_snippet("<cmdline>".to_owned(), (&opts.input.input as &str).into())?
124 PathBuf::from("<cmdline>").into(),
125 (&opts.input.input as &str).into(),
126 )?
127 } else if opts.input.input == "-" {124 } else if opts.input.input == "-" {
128 let mut input = Vec::new();125 let mut input = Vec::new();
129 std::io::stdin().read_to_end(&mut input)?;126 std::io::stdin().read_to_end(&mut input)?;
130 let input_str = std::str::from_utf8(&input)?.into();127 let input_str = std::str::from_utf8(&input)?.into();
131 s.evaluate_snippet_raw(PathBuf::from("<stdin>").into(), input_str)?128 s.evaluate_snippet("<stdin>".to_owned(), input_str)?
132 } else {129 } else {
133 s.evaluate_file_raw(&PathBuf::from(opts.input.input))?130 s.import(s.resolve_file(&PathBuf::new(), &opts.input.input)?)?
134 };131 };
135132
136 let val = s.with_tla(val)?;133 let val = s.with_tla(val)?;
modifiedcrates/jrsonnet-cli/src/ext.rsdiffbeforeafterboth
108 s.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());108 s.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into());
109 }109 }
110 for ext in self.ext_code.iter() {110 for ext in self.ext_code.iter() {
111 s.add_ext_code((&ext.name as &str).into(), (&ext.value as &str).into())?;111 s.add_ext_code(&ext.name as &str, (&ext.value as &str).into())?;
112 }112 }
113 for ext in self.ext_code_file.iter() {113 for ext in self.ext_code_file.iter() {
114 s.add_ext_code((&ext.name as &str).into(), (&ext.value as &str).into())?;114 s.add_ext_code(&ext.name as &str, (&ext.value as &str).into())?;
115 }115 }
116 Ok(())116 Ok(())
117 }117 }
modifiedcrates/jrsonnet-cli/src/tla.rsdiffbeforeafterboth
55 s.add_tla_str((&tla.name as &str).into(), (&tla.value as &str).into())55 s.add_tla_str((&tla.name as &str).into(), (&tla.value as &str).into())
56 }56 }
57 for tla in self.tla_code.iter() {57 for tla in self.tla_code.iter() {
58 s.add_tla_code((&tla.name as &str).into(), (&tla.value as &str).into())?;58 s.add_tla_code((&tla.name as &str).into(), &tla.value as &str)?;
59 }59 }
60 for tla in self.tla_code_file.iter() {60 for tla in self.tla_code_file.iter() {
61 s.add_tla_code((&tla.name as &str).into(), (&tla.value as &str).into())?;61 s.add_tla_code((&tla.name as &str).into(), &tla.value as &str)?;
62 }62 }
63 Ok(())63 Ok(())
64 }64 }
modifiedcrates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth
28jrsonnet-types = { path = "../jrsonnet-types", version = "0.4.2" }28jrsonnet-types = { path = "../jrsonnet-types", version = "0.4.2" }
29jrsonnet-macros = { path = "../jrsonnet-macros", version = "0.4.2" }29jrsonnet-macros = { path = "../jrsonnet-macros", version = "0.4.2" }
30pathdiff = "0.2.1"30pathdiff = "0.2.1"
31hashbrown = "0.12.1"
32static_assertions = "1.1.0"
3133
32md5 = "0.7.0"34md5 = "0.7.0"
33base64 = "0.13.0"35base64 = "0.13.0"
modifiedcrates/jrsonnet-evaluator/build.rsdiffbeforeafterboth
1use std::{1use std::{borrow::Cow, env, fs::File, io::Write, path::Path};
2 env,
3 fs::File,
4 io::Write,
5 path::{Path, PathBuf},
6};
72
8use bincode::serialize;3use bincode::serialize;
9use jrsonnet_parser::{parse, ParserSettings};4use jrsonnet_parser::{parse, ParserSettings, Source};
10use jrsonnet_stdlib::STDLIB_STR;5use jrsonnet_stdlib::STDLIB_STR;
116
12fn main() {7fn main() {
13 let parsed = parse(8 let parsed = parse(
14 STDLIB_STR,9 STDLIB_STR,
15 &ParserSettings {10 &ParserSettings {
16 file_name: PathBuf::from("std.jsonnet").into(),11 file_name: Source::new_virtual(Cow::Borrowed("<std>")),
17 },12 },
18 )13 )
19 .expect("parse");14 .expect("parse");
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
1use std::{1use std::{fmt::Debug, path::PathBuf};
2 fmt::Debug,
3 path::{Path, PathBuf},
4 rc::Rc,
5};
62
7use gcmodule::Trace;3use gcmodule::Trace;
8use jrsonnet_interner::IStr;4use jrsonnet_interner::IStr;
9use jrsonnet_parser::{BinaryOpType, ExprLocation, UnaryOpType};5use jrsonnet_parser::{BinaryOpType, ExprLocation, Source, UnaryOpType};
10use jrsonnet_types::ValType;6use jrsonnet_types::ValType;
11use thiserror::Error;7use thiserror::Error;
128
85 StandaloneSuper,81 StandaloneSuper,
8682
87 #[error("can't resolve {1} from {0}")]83 #[error("can't resolve {1} from {0}")]
88 ImportFileNotFound(PathBuf, PathBuf),84 ImportFileNotFound(PathBuf, String),
89 #[error("resolved file not found: {0}")]85 #[error("resolved file not found: {0}")]
90 ResolvedFileNotFound(PathBuf),86 ResolvedFileNotFound(PathBuf),
91 #[error("imported file is not valid utf-8: {0:?}")]87 #[error("imported file is not valid utf-8: {0:?}")]
94 ImportIo(String),90 ImportIo(String),
95 #[error("tried to import {1} from {0}, but imports is not supported")]91 #[error("tried to import {1} from {0}, but imports is not supported")]
96 ImportNotSupported(PathBuf, PathBuf),92 ImportNotSupported(PathBuf, PathBuf),
93 #[error("can't import from virtual file")]
94 CantImportFromVirtualFile,
97 #[error(95 #[error(
98 "syntax error: expected {}, got {:?}",96 "syntax error: expected {}, got {:?}",
99 .error.expected,97 .error.expected,
100 .source_code.chars().nth(error.location.offset)98 .source_code.chars().nth(error.location.offset)
101 .map_or_else(|| "EOF".into(), |c| c.to_string())99 .map_or_else(|| "EOF".into(), |c| c.to_string())
102 )]100 )]
103 ImportSyntaxError {101 ImportSyntaxError {
104 #[skip_trace]
105 path: Rc<Path>,102 path: Source,
106 source_code: IStr,103 source_code: IStr,
107 #[skip_trace]104 #[skip_trace]
108 error: Box<jrsonnet_parser::ParseError>,105 error: Box<jrsonnet_parser::ParseError>,
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
452 Ok(Some(v)) => Ok(v),452 Ok(Some(v)) => Ok(v),
453 Ok(None) => throw!(NoSuchField(key.clone())),453 Ok(None) => throw!(NoSuchField(key.clone())),
454 Err(e) if matches!(e.error(), MagicThisFileUsed) => {454 Err(e) if matches!(e.error(), MagicThisFileUsed) => {
455 Ok(Val::Str(loc.0.to_string_lossy().into()))455 Ok(Val::Str(loc.0.full_path().into()))
456 }456 }
457 Err(e) => Err(e),457 Err(e) => Err(e),
458 },458 },
617617
618 std_slice(indexable.into_indexable()?, start, end, step)?618 std_slice(indexable.into_indexable()?, start, end, step)?
619 }619 }
620 Import(path) => {620 i @ (Import(path) | ImportStr(path) | ImportBin(path)) => {
621 let tmp = loc.clone().0;621 let tmp = loc.clone().0;
622 let mut import_location = tmp.to_path_buf();622 let import_location = tmp
623 .path()
624 .map(|p| {
625 let mut p = p.to_owned();
626 p.pop();
627 p
628 })
629 .unwrap_or_default();
623 import_location.pop();630 let path = s.resolve_file(&import_location, path as &str)?;
631 match i {
624 s.push(632 Import(_) => s.push(
625 CallLocation::new(loc),633 CallLocation::new(loc),
626 || format!("import {:?}", path),634 || format!("import {:?}", path.clone()),
627 || s.import_file(&import_location, path),635 || s.import(path.clone()),
628 )?636 )?,
637 ImportStr(_) => Val::Str(s.import_str(path)?),
638 ImportBin(_) => Val::Arr(ArrValue::Bytes(s.import_bin(path)?)),
639 _ => unreachable!(),
640 }
629 }641 }
630 ImportStr(path) => {
631 let tmp = loc.clone().0;
632 let mut import_location = tmp.to_path_buf();
633 import_location.pop();
634 Val::Str(s.import_file_str(&import_location, path)?)
635 }
636 ImportBin(path) => {
637 let tmp = loc.clone().0;
638 let mut import_location = tmp.to_path_buf();
639 import_location.pop();
640 let bytes = s.import_file_bin(&import_location, path)?;
641 Val::Arr(ArrValue::Bytes(bytes))
642 }
643 })642 })
644}643}
645644
modifiedcrates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth
47 }47 }
48}48}
4949
50#[derive(Clone)]
50pub enum TlaArg {51pub enum TlaArg {
51 String(IStr),52 String(IStr),
52 Code(LocExpr),53 Code(LocExpr),
modifiedcrates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth
1use std::{borrow::Cow, path::Path, rc::Rc};1use std::borrow::Cow;
22
3use gcmodule::Trace;3use gcmodule::Trace;
44
51 &self.params51 &self.params
52 }52 }
5353
54 fn call(&self, s: State, ctx: Context, loc: CallLocation, args: &dyn ArgsLike) -> Result<Val> {54 fn call(&self, s: State, ctx: Context, _loc: CallLocation, args: &dyn ArgsLike) -> Result<Val> {
55 let args = parse_builtin_call(s.clone(), ctx, &self.params, args, true)?;55 let args = parse_builtin_call(s.clone(), ctx, &self.params, args, true)?;
56 let mut out_args = Vec::with_capacity(self.params.len());56 let mut out_args = Vec::with_capacity(self.params.len());
57 for p in &self.params {57 for p in &self.params {
58 out_args.push(args[&p.name].evaluate(s.clone())?);58 out_args.push(args[&p.name].evaluate(s.clone())?);
59 }59 }
60 self.handler.call(s, loc.0.map(|l| l.0.clone()), &out_args)60 self.handler.call(s, &out_args)
61 }61 }
62}62}
6363
64pub trait NativeCallbackHandler: Trace {64pub trait NativeCallbackHandler: Trace {
65 fn call(&self, s: State, from: Option<Rc<Path>>, args: &[Val]) -> Result<Val>;65 fn call(&self, s: State, args: &[Val]) -> Result<Val>;
66}66}
6767
modifiedcrates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterboth
1/// Macros to help deal with Gc1/// Macros to help deal with Gc
2use std::{2use std::{
3 borrow::{Borrow, BorrowMut},3 borrow::{Borrow, BorrowMut},
4 collections::{HashMap, HashSet},4 collections::HashSet,
5 hash::BuildHasherDefault,5 hash::BuildHasherDefault,
6 ops::{Deref, DerefMut},6 ops::{Deref, DerefMut},
7};7};
88
9use gcmodule::{Trace, Tracer};9use gcmodule::{Trace, Tracer};
10use hashbrown::HashMap;
10use rustc_hash::{FxHashMap, FxHashSet};11use rustc_hash::{FxHashSet, FxHasher};
1112
12/// Replacement for box, which assumes that the underlying type is [`Trace`]13/// Replacement for box, which assumes that the underlying type is [`Trace`]
13/// Used in places, where `Cc<dyn Trait>` should be used instead, but it can't, because `CoerceUnsiced` is not stable14/// Used in places, where `Cc<dyn Trait>` should be used instead, but it can't, because `CoerceUnsiced` is not stable
115 }116 }
116}117}
117118
118#[derive(Clone)]
119pub struct GcHashMap<K, V>(pub FxHashMap<K, V>);119pub struct GcHashMap<K, V>(pub HashMap<K, V, BuildHasherDefault<FxHasher>>);
120impl<K, V> GcHashMap<K, V> {120impl<K, V> GcHashMap<K, V> {
121 pub fn new() -> Self {121 pub fn new() -> Self {
122 Self(HashMap::default())122 Self(HashMap::default())
123 }123 }
124 pub fn with_capacity(capacity: usize) -> Self {124 pub fn with_capacity(capacity: usize) -> Self {
125 Self(FxHashMap::with_capacity_and_hasher(125 Self(HashMap::with_capacity_and_hasher(
126 capacity,126 capacity,
127 BuildHasherDefault::default(),127 BuildHasherDefault::default(),
128 ))128 ))
141 }141 }
142}142}
143impl<K, V> Deref for GcHashMap<K, V> {143impl<K, V> Deref for GcHashMap<K, V> {
144 type Target = FxHashMap<K, V>;144 type Target = HashMap<K, V, BuildHasherDefault<FxHasher>>;
145145
146 fn deref(&self) -> &Self::Target {146 fn deref(&self) -> &Self::Target {
147 &self.0147 &self.0
modifiedcrates/jrsonnet-evaluator/src/import.rsdiffbeforeafterboth
1use std::{1use std::{
2 any::Any,2 any::Any,
3 convert::TryFrom,
4 fs,3 fs,
5 io::Read,4 io::Read,
6 path::{Path, PathBuf},5 path::{Path, PathBuf},
7 rc::Rc,
8};6};
97
10use fs::File;8use fs::File;
11use jrsonnet_interner::IStr;
129
13use crate::{10use crate::{
14 error::{Error::*, Result},11 error::{Error::*, Result},
20 /// Resolves real file path, e.g. `(/home/user/manifests, b.libjsonnet)` can correspond17 /// Resolves real file path, e.g. `(/home/user/manifests, b.libjsonnet)` can correspond
21 /// both to `/home/user/manifests/b.libjsonnet` and to `/home/user/${vendor}/b.libjsonnet`18 /// both to `/home/user/manifests/b.libjsonnet` and to `/home/user/${vendor}/b.libjsonnet`
22 /// where `${vendor}` is a library path.19 /// where `${vendor}` is a library path.
23 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>>;20 fn resolve_file(&self, from: &Path, path: &str) -> Result<PathBuf>;
2421
25 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;22 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;
26
27 /// Reads file from filesystem, should be used only with path received from `resolve_file`
28 fn load_file_str(&self, resolved: &Path) -> Result<IStr> {
29 Ok(IStr::try_from(&self.load_file_contents(resolved)? as &[u8])
30 .map_err(|_| ImportBadFileUtf8(resolved.to_path_buf()))?)
31 }
32
33 /// Reads file from filesystem, should be used only with path received from `resolve_file`
34 fn load_file_bin(&self, resolved: &Path) -> Result<Rc<[u8]>> {
35 Ok(self.load_file_contents(resolved)?.into())
36 }
3723
38 /// # Safety24 /// # Safety
39 ///25 ///
46/// Dummy resolver, can't resolve/load any file32/// Dummy resolver, can't resolve/load any file
47pub struct DummyImportResolver;33pub struct DummyImportResolver;
48impl ImportResolver for DummyImportResolver {34impl ImportResolver for DummyImportResolver {
49 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {35 fn resolve_file(&self, from: &Path, path: &str) -> Result<PathBuf> {
50 throw!(ImportNotSupported(from.into(), path.into()))36 throw!(ImportNotSupported(from.into(), path.into()))
51 }37 }
5238
73 pub library_paths: Vec<PathBuf>,59 pub library_paths: Vec<PathBuf>,
74}60}
75impl ImportResolver for FileImportResolver {61impl ImportResolver for FileImportResolver {
76 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {62 fn resolve_file(&self, from: &Path, path: &str) -> Result<PathBuf> {
77 let mut direct = from.to_path_buf();63 let mut direct = from.to_path_buf();
78 direct.push(path);64 direct.push(path);
79 if direct.exists() {65 if direct.exists() {
80 Ok(direct.into())66 Ok(direct.canonicalize().map_err(|e| ImportIo(e.to_string()))?)
81 } else {67 } else {
82 for library_path in &self.library_paths {68 for library_path in &self.library_paths {
83 let mut cloned = library_path.clone();69 let mut cloned = library_path.clone();
84 cloned.push(path);70 cloned.push(path);
85 if cloned.exists() {71 if cloned.exists() {
86 return Ok(cloned.into());72 return Ok(cloned.canonicalize().map_err(|e| ImportIo(e.to_string()))?);
87 }73 }
88 }74 }
89 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))75 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
38pub mod val;38pub mod val;
3939
40use std::{40use std::{
41 borrow::Cow,
41 cell::{Ref, RefCell, RefMut},42 cell::{Ref, RefCell, RefMut},
42 collections::HashMap,43 collections::HashMap,
43 fmt::{self, Debug},44 fmt::{self, Debug},
52use function::{builtin::Builtin, CallLocation, TlaArg};53use function::{builtin::Builtin, CallLocation, TlaArg};
53use gc::{GcHashMap, TraceBox};54use gc::{GcHashMap, TraceBox};
54use gcmodule::{Cc, Trace, Weak};55use gcmodule::{Cc, Trace, Weak};
56use hashbrown::hash_map::RawEntryMut;
55pub use import::*;57pub use import::*;
58use jrsonnet_interner::IBytes;
56pub use jrsonnet_interner::IStr;59pub use jrsonnet_interner::IStr;
57pub use jrsonnet_parser as parser;60pub use jrsonnet_parser as parser;
58use jrsonnet_parser::*;61use jrsonnet_parser::*;
96 /// Limits amount of stack trace items preserved99 /// Limits amount of stack trace items preserved
97 pub max_trace: usize,100 pub max_trace: usize,
98 /// Used for s`td.extVar`101 /// Used for s`td.extVar`
99 pub ext_vars: HashMap<IStr, Val>,102 pub ext_vars: HashMap<IStr, TlaArg>,
100 /// Used for ext.native103 /// Used for ext.native
101 pub ext_natives: HashMap<IStr, Cc<TraceBox<dyn Builtin>>>,104 pub ext_natives: HashMap<IStr, Cc<TraceBox<dyn Builtin>>>,
102 /// TLA vars105 /// TLA vars
141 stack_generation: usize,144 stack_generation: usize,
142145
143 breakpoints: Breakpoints,146 breakpoints: Breakpoints,
147
144 /// Contains file source codes and evaluation results for imports and pretty-printed stacktraces148 /// Contains file source codes and evaluation results for imports and pretty-printed stacktraces
145 files: GcHashMap<Rc<Path>, FileData>,149 files: GcHashMap<PathBuf, FileData>,
146 str_files: GcHashMap<Rc<Path>, IStr>,150 /// Contains tla arguments and others, which aren't needed to be obtained by name
147 bin_files: GcHashMap<Rc<Path>, Rc<[u8]>>,151 volatile_files: GcHashMap<String, String>,
148}152}
153struct FileData {
154 string: Option<IStr>,
155 bytes: Option<IBytes>,
156 parsed: Option<LocExpr>,
157 evaluated: Option<Val>,
149158
150pub struct FileData {
151 source_code: IStr,
152 parsed: LocExpr,
153 evaluated: Option<Val>,159 evaluating: bool,
154}160}
161impl FileData {
162 fn new_string(data: IStr) -> Self {
163 Self {
164 string: Some(data),
165 bytes: None,
166 parsed: None,
167 evaluated: None,
168 evaluating: false,
169 }
170 }
171 fn new_bytes(data: IBytes) -> Self {
172 Self {
173 string: None,
174 bytes: Some(data),
175 parsed: None,
176 evaluated: None,
177 evaluating: false,
178 }
179 }
180}
155181
156#[allow(clippy::type_complexity)]182#[allow(clippy::type_complexity)]
157pub struct Breakpoint {183pub struct Breakpoint {
198pub struct State(Rc<EvaluationStateInternals>);224pub struct State(Rc<EvaluationStateInternals>);
199225
200impl State {226impl State {
201 /// Parses and adds file as loaded227 pub fn import_str(&self, path: PathBuf) -> Result<IStr> {
202 pub fn add_file(&self, path: Rc<Path>, source_code: IStr) -> Result<LocExpr> {
203 let parsed = parse(228 let mut data = self.data_mut();
204 &source_code,
205 &ParserSettings {
206 file_name: path.clone(),
207 },229 let mut file = data.files.raw_entry_mut().from_key(&path);
208 )
209 .map_err(|error| ImportSyntaxError {
210 error: Box::new(error),
211 path: path.clone(),
212 source_code: source_code.clone(),
213 })?;
214 self.add_parsed_file(path, source_code, parsed.clone())?;
215230
216 Ok(parsed)231 let file = match file {
232 RawEntryMut::Occupied(ref mut d) => d.get_mut(),
233 RawEntryMut::Vacant(v) => {
234 let data = self.settings().import_resolver.load_file_contents(&path)?;
235 v.insert(
236 path.clone(),
237 FileData::new_string(
238 std::str::from_utf8(&data)
239 .map_err(|_| ImportBadFileUtf8(path.clone()))?
240 .into(),
241 ),
242 )
243 .1
244 }
245 };
246 if let Some(str) = &file.string {
247 return Ok(str.clone());
248 }
249 if file.string.is_none() {
250 file.string = Some(
251 file.bytes
252 .as_ref()
253 .expect("either string or bytes should be set")
254 .clone()
255 .cast_str()
256 .ok_or_else(|| ImportBadFileUtf8(path.clone()))?,
257 );
258 }
259 Ok(file.string.as_ref().expect("just set").clone())
217 }260 }
261 pub fn import_bin(&self, path: PathBuf) -> Result<IBytes> {
262 let mut data = self.data_mut();
263 let mut file = data.files.raw_entry_mut().from_key(&path);
218264
219 pub fn reset_evaluation_state(&self, name: &Path) {265 let file = match file {
266 RawEntryMut::Occupied(ref mut d) => d.get_mut(),
267 RawEntryMut::Vacant(v) => {
268 let data = self.settings().import_resolver.load_file_contents(&path)?;
269 v.insert(path.clone(), FileData::new_bytes(data.as_slice().into()))
270 .1
271 }
272 };
273 if let Some(str) = &file.bytes {
220 self.data_mut()274 return Ok(str.clone());
221 .files275 }
276 if file.bytes.is_none() {
222 .get_mut(name)277 file.bytes = Some(
278 file.string
279 .as_ref()
223 .expect("file not found")280 .expect("either string or bytes should be set")
224 .evaluated281 .clone()
225 .take();282 .cast_bytes(),
283 );
284 }
285 Ok(file.bytes.as_ref().expect("just set").clone())
226 }286 }
287 pub fn import(&self, path: PathBuf) -> Result<Val> {
288 let mut data = self.data_mut();
289 let mut file = data.files.raw_entry_mut().from_key(&path);
227290
228 /// Adds file by source code and parsed expr291 let file = match file {
292 RawEntryMut::Occupied(ref mut d) => d.get_mut(),
293 RawEntryMut::Vacant(v) => {
229 pub fn add_parsed_file(294 let data = self.settings().import_resolver.load_file_contents(&path)?;
230 &self,295 v.insert(
296 path.clone(),
231 name: Rc<Path>,297 FileData::new_string(
298 std::str::from_utf8(&data)
299 .map_err(|_| ImportBadFileUtf8(path.clone()))?
300 .into(),
232 source_code: IStr,301 ),
302 )
303 .1
304 }
305 };
306 if let Some(val) = &file.evaluated {
307 return Ok(val.clone());
308 }
309 if file.string.is_none() {
310 file.string = Some(
311 std::str::from_utf8(
312 file.bytes
313 .as_ref()
314 .expect("either string or bytes should be set"),
233 parsed: LocExpr,315 )
316 .map_err(|_| ImportBadFileUtf8(path.clone()))?
317 .into(),
234 ) -> Result<()> {318 );
319 }
320 let code = file.string.as_ref().expect("just set");
235 self.data_mut().files.insert(321 let file_name = Source::new(path.clone()).expect("resolver should return correct name");
322 if file.parsed.is_none() {
236 name,323 file.parsed = Some(
324 jrsonnet_parser::parse(
325 code,
237 FileData {326 &ParserSettings {
238 source_code,327 file_name: file_name.clone(),
239 parsed,328 },
240 evaluated: None,329 )
330 .map_err(|e| ImportSyntaxError {
331 path: file_name,
241 },332 source_code: code.clone(),
333 error: Box::new(e),
334 })?,
242 );335 );
336 }
337 let parsed = file.parsed.as_ref().expect("just set").clone();
338 if file.evaluating {
339 throw!(InfiniteRecursionDetected)
340 }
341 file.evaluating = true;
342 // Dropping file here, as it borrows data, which may be used in evaluation
343 drop(data);
344 let res = evaluate(self.clone(), self.create_default_context(), &parsed);
243345
244 Ok(())346 let mut data = self.data_mut();
347 let mut file = data.files.raw_entry_mut().from_key(&path);
348
349 let file = match file {
350 RawEntryMut::Occupied(ref mut d) => d.get_mut(),
351 RawEntryMut::Vacant(_) => unreachable!("this file was just here!"),
352 };
353 file.evaluating = false;
354 match res {
355 Ok(v) => {
356 file.evaluated = Some(v.clone());
357 Ok(v)
358 }
359 Err(e) => Err(e),
360 }
245 }361 }
362
246 pub fn get_source(&self, name: &Path) -> Option<IStr> {363 pub fn get_source(&self, name: Source) -> Option<String> {
247 let ro_map = &self.data().files;364 let data = self.data();
365 match name.repr() {
366 Ok(real) => data
367 .files
248 ro_map.get(name).map(|value| value.source_code.clone())368 .get(real)
369 .and_then(|f| f.string.as_ref())
370 .map(ToString::to_string),
371 Err(e) => data.volatile_files.get(e).map(ToOwned::to_owned),
372 }
249 }373 }
250 pub fn map_source_locations(&self, file: &Path, locs: &[usize]) -> Vec<CodeLocation> {374 pub fn map_source_locations(&self, file: Source, locs: &[u32]) -> Vec<CodeLocation> {
251 offset_to_location(&self.get_source(file).unwrap_or_else(|| "".into()), locs)375 offset_to_location(&self.get_source(file).unwrap_or_else(|| "".into()), locs)
252 }376 }
253 pub fn map_from_source_location(377 pub fn map_from_source_location(
254 &self,378 &self,
255 file: &Path,379 file: Source,
256 line: usize,380 line: usize,
257 column: usize,381 column: usize,
258 ) -> Option<usize> {382 ) -> Option<usize> {
262 column,386 column,
263 )387 )
264 }388 }
265 pub fn import_file(&self, from: &Path, path: &Path) -> Result<Val> {
266 let file_path = self.resolve_file(from, path)?;
267 {
268 let data = self.data();
269 let files = &data.files;
270 if files.contains_key(&file_path as &Path) {
271 drop(data);
272 return self.evaluate_loaded_file_raw(&file_path);
273 }
274 }
275 let contents = self.load_file_str(&file_path)?;
276 self.add_file(file_path.clone(), contents)?;
277 self.evaluate_loaded_file_raw(&file_path)
278 }
279 pub(crate) fn import_file_str(&self, from: &Path, path: &Path) -> Result<IStr> {
280 let path = self.resolve_file(from, path)?;
281 if !self.data().str_files.contains_key(&path) {
282 let file_str = self.load_file_str(&path)?;
283 self.data_mut().str_files.insert(path.clone(), file_str);
284 }
285 Ok(self.data().str_files.get(&path).cloned().unwrap())
286 }
287 pub(crate) fn import_file_bin(&self, from: &Path, path: &Path) -> Result<Rc<[u8]>> {
288 let path = self.resolve_file(from, path)?;
289 if !self.data().bin_files.contains_key(&path) {
290 let file_bin = self.load_file_bin(&path)?;
291 self.data_mut().bin_files.insert(path.clone(), file_bin);
292 }
293 Ok(self.data().bin_files.get(&path).cloned().unwrap())
294 }
295
296 fn evaluate_loaded_file_raw(&self, name: &Path) -> Result<Val> {
297 let expr: LocExpr = {
298 let ro_map = &self.data().files;
299 let value = ro_map
300 .get(name)
301 .unwrap_or_else(|| panic!("file not added: {:?}", name));
302 if let Some(ref evaluated) = value.evaluated {
303 return Ok(evaluated.clone());
304 }
305 value.parsed.clone()
306 };
307 let value = evaluate(self.clone(), self.create_default_context(), &expr)?;
308 {
309 self.data_mut()
310 .files
311 .get_mut(name)
312 .unwrap()
313 .evaluated
314 .replace(value.clone());
315 }
316 Ok(value)
317 }
318
319 /// Adds standard library global variable (std) to this evaluator389 /// Adds standard library global variable (std) to this evaluator
320 pub fn with_stdlib(&self) -> &Self {390 pub fn with_stdlib(&self) -> &Self {
321 use jrsonnet_stdlib::STDLIB_STR;391 let val = evaluate(
322 let std_path: Rc<Path> = PathBuf::from("std.jsonnet").into();
323
324 self.add_parsed_file(392 self.clone(),
325 std_path.clone(),
326 STDLIB_STR.to_owned().into(),393 self.create_default_context(),
327 stdlib::get_parsed_stdlib(),394 &stdlib::get_parsed_stdlib(),
328 )395 )
329 .expect("stdlib is correct");396 .expect("std should not fail");
330 let val = self
331 .evaluate_loaded_file_raw(&std_path)
332 .expect("stdlib is correct");
333 self.settings_mut().globals.insert("std".into(), val);397 self.settings_mut().globals.insert("std".into(), val);
334 self398 self
335 }399 }
506570
507/// Raw methods evaluate passed values but don't perform TLA execution571/// Raw methods evaluate passed values but don't perform TLA execution
508impl State {572impl State {
509 pub fn evaluate_file_raw(&self, name: &Path) -> Result<Val> {
510 self.import_file(&std::env::current_dir().expect("cwd"), name)
511 }
512 pub fn evaluate_file_raw_nocwd(&self, name: &Path) -> Result<Val> {
513 self.import_file(&PathBuf::from("."), name)
514 }
515 /// Parses and evaluates the given snippet573 /// Parses and evaluates the given snippet
516 pub fn evaluate_snippet_raw(&self, source: Rc<Path>, code: IStr) -> Result<Val> {574 pub fn evaluate_snippet(&self, name: String, code: String) -> Result<Val> {
517 let parsed = parse(575 let source = Source::new_virtual(Cow::Owned(name.clone()));
576 let parsed = jrsonnet_parser::parse(
518 &code,577 &code,
519 &ParserSettings {578 &ParserSettings {
520 file_name: source.clone(),579 file_name: source.clone(),
521 },580 },
522 )581 )
523 .map_err(|e| ImportSyntaxError {582 .map_err(|e| ImportSyntaxError {
524 path: source.clone(),583 path: source,
525 source_code: code.clone(),584 source_code: code.clone().into(),
526 error: Box::new(e),585 error: Box::new(e),
527 })?;586 })?;
528 self.add_parsed_file(source, code, parsed.clone())?;587 self.data_mut().volatile_files.insert(name, code);
529 self.evaluate_expr_raw(parsed)588 evaluate(self.clone(), self.create_default_context(), &parsed)
530 }589 }
531 /// Evaluates the parsed expression
532 pub fn evaluate_expr_raw(&self, code: LocExpr) -> Result<Val> {
533 evaluate(self.clone(), self.create_default_context(), &code)
534 }
535}590}
536591
537/// Settings utilities592/// Settings utilities
538impl State {593impl State {
539 pub fn add_ext_var(&self, name: IStr, value: Val) {594 pub fn add_ext_var(&self, name: IStr, value: Val) {
540 self.settings_mut().ext_vars.insert(name, value);595 self.settings_mut()
596 .ext_vars
597 .insert(name, TlaArg::Val(value));
541 }598 }
542 pub fn add_ext_str(&self, name: IStr, value: IStr) {599 pub fn add_ext_str(&self, name: IStr, value: IStr) {
543 self.add_ext_var(name, Val::Str(value));600 self.settings_mut()
601 .ext_vars
602 .insert(name, TlaArg::String(value));
544 }603 }
545 pub fn add_ext_code(&self, name: IStr, code: IStr) -> Result<()> {604 pub fn add_ext_code(&self, name: &str, code: String) -> Result<()> {
546 let value =605 let source_name = format!("<extvar:{}>", name);
547 self.evaluate_snippet_raw(PathBuf::from(format!("ext_code {}", name)).into(), code)?;606 let source = Source::new_virtual(Cow::Owned(source_name.clone()));
607 let parsed = jrsonnet_parser::parse(
608 &code,
609 &ParserSettings {
610 file_name: source.clone(),
611 },
612 )
613 .map_err(|e| ImportSyntaxError {
614 path: source,
615 source_code: code.clone().into(),
616 error: Box::new(e),
617 })?;
548 self.add_ext_var(name, value);618 self.data_mut().volatile_files.insert(source_name, code);
619 self.settings_mut()
620 .ext_vars
621 .insert(name.into(), TlaArg::Code(parsed));
549 Ok(())622 Ok(())
550 }623 }
551624
559 .tla_vars632 .tla_vars
560 .insert(name, TlaArg::String(value));633 .insert(name, TlaArg::String(value));
561 }634 }
562 pub fn add_tla_code(&self, name: IStr, code: IStr) -> Result<()> {635 pub fn add_tla_code(&self, name: IStr, code: &str) -> Result<()> {
563 let parsed = self.add_file(PathBuf::from(format!("tla_code {}", name)).into(), code)?;636 let source_name = format!("<top-level-arg:{}>", name);
637 let source = Source::new_virtual(Cow::Owned(source_name.clone()));
638 let parsed = jrsonnet_parser::parse(
639 code,
640 &ParserSettings {
641 file_name: source.clone(),
642 },
643 )
644 .map_err(|e| ImportSyntaxError {
645 path: source,
646 source_code: code.into(),
647 error: Box::new(e),
648 })?;
649 self.data_mut()
650 .volatile_files
651 .insert(source_name, code.to_owned());
564 self.settings_mut()652 self.settings_mut()
565 .tla_vars653 .tla_vars
566 .insert(name, TlaArg::Code(parsed));654 .insert(name, TlaArg::Code(parsed));
567 Ok(())655 Ok(())
568 }656 }
569657
570 pub fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {658 pub fn resolve_file(&self, from: &Path, path: &str) -> Result<PathBuf> {
571 self.settings().import_resolver.resolve_file(from, path)659 self.settings()
572 }660 .import_resolver
573 pub fn load_file_str(&self, path: &Path) -> Result<IStr> {
574 self.settings().import_resolver.load_file_str(path)
575 }661 .resolve_file(from, path.as_ref())
576 pub fn load_file_bin(&self, path: &Path) -> Result<Rc<[u8]>> {
577 self.settings().import_resolver.load_file_bin(path)
578 }662 }
579663
580 pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {664 pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {
modifiedcrates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth
14pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);14pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);
1515
16impl LayeredHashMap {16impl LayeredHashMap {
17 pub fn iter_keys(self, mut handler: impl FnMut(IStr)) {
18 for (k, _) in self.0.current.iter() {
19 handler(k.clone());
20 }
21 if let Some(parent) = self.0.parent.clone() {
22 parent.iter_keys(handler);
23 }
24 }
25
17 pub fn extend(self, new_layer: GcHashMap<IStr, Thunk<Val>>) -> Self {26 pub fn extend(self, new_layer: GcHashMap<IStr, Thunk<Val>>) -> Self {
18 Self(Cc::new(LayeredHashMapInternals {27 Self(Cc::new(LayeredHashMapInternals {
modifiedcrates/jrsonnet-evaluator/src/stdlib/expr.rsdiffbeforeafterboth
1use std::path::PathBuf;1use std::borrow::Cow;
22
3use jrsonnet_parser::{LocExpr, ParserSettings};3use jrsonnet_parser::{LocExpr, ParserSettings, Source};
44
5thread_local! {5thread_local! {
6 /// To avoid parsing again when issued from the same thread6 /// To avoid parsing again when issued from the same thread
16 jrsonnet_parser::parse(16 jrsonnet_parser::parse(
17 jrsonnet_stdlib::STDLIB_STR,17 jrsonnet_stdlib::STDLIB_STR,
18 &ParserSettings {18 &ParserSettings {
19 file_name: PathBuf::from("std.jsonnet").into(),19 file_name: Source::new_virtual(Cow::Borrowed("<std>")),
20 },20 },
21 )21 )
22 .unwrap()22 .unwrap()
modifiedcrates/jrsonnet-evaluator/src/stdlib/mod.rsdiffbeforeafterboth
55
6use format::{format_arr, format_obj};6use format::{format_arr, format_obj};
7use gcmodule::Cc;7use gcmodule::Cc;
8use jrsonnet_interner::IStr;8use jrsonnet_interner::{IBytes, IStr};
9use serde::Deserialize;9use serde::Deserialize;
10use serde_yaml::DeserializingQuirks;10use serde_yaml::DeserializingQuirks;
1111
12use crate::{12use crate::{
13 error::{Error::*, Result},13 error::{Error::*, Result},
14 function::{builtin::StaticBuiltin, CallLocation, FuncVal},14 function::{builtin::StaticBuiltin, ArgLike, CallLocation, FuncVal},
15 operator::evaluate_mod_op,15 operator::evaluate_mod_op,
16 stdlib::manifest::{manifest_yaml_ex, ManifestYamlOptions},16 stdlib::manifest::{manifest_yaml_ex, ManifestYamlOptions},
17 throw,17 throw,
18 typed::{Any, BoundedUsize, Bytes, Either2, Either4, PositiveF64, Typed, VecVal, M1},18 typed::{Any, BoundedUsize, Either2, Either4, PositiveF64, Typed, VecVal, M1},
19 val::{equals, primitive_equals, ArrValue, IndexableVal, Slice},19 val::{equals, primitive_equals, ArrValue, IndexableVal, Slice},
20 Either, ObjValue, State, Val,20 Either, ObjValue, State, Val,
21};21};
365365
366#[jrsonnet_macros::builtin]366#[jrsonnet_macros::builtin]
367fn builtin_ext_var(s: State, x: IStr) -> Result<Any> {367fn builtin_ext_var(s: State, x: IStr) -> Result<Any> {
368 let ctx = s.create_default_context();
368 Ok(Any(s369 Ok(Any(s
370 .clone()
369 .settings()371 .settings()
370 .ext_vars372 .ext_vars
371 .get(&x)373 .get(&x)
374 .cloned()
375 .ok_or(UndefinedExternalVariable(x))?
372 .cloned()376 .evaluate_arg(s.clone(), ctx, true)?
373 .ok_or(UndefinedExternalVariable(x))?))377 .evaluate(s)?))
374}378}
375379
376#[jrsonnet_macros::builtin]380#[jrsonnet_macros::builtin]
489}493}
490494
491#[jrsonnet_macros::builtin]495#[jrsonnet_macros::builtin]
492fn builtin_encode_utf8(str: IStr) -> Result<Bytes> {496fn builtin_encode_utf8(str: IStr) -> Result<IBytes> {
493 Ok(Bytes(str.bytes().collect::<Vec<u8>>().into()))497 Ok(str.cast_bytes())
494}498}
495499
496#[jrsonnet_macros::builtin]500#[jrsonnet_macros::builtin]
497fn builtin_decode_utf8(arr: Bytes) -> Result<IStr> {501fn builtin_decode_utf8(arr: IBytes) -> Result<IStr> {
498 Ok(std::str::from_utf8(&arr.0)502 Ok(arr
503 .cast_str()
499 .map_err(|_| RuntimeError("bad utf8".into()))?504 .ok_or_else(|| RuntimeError("bad utf8".into()))?)
500 .into())
501}505}
502506
503#[jrsonnet_macros::builtin]507#[jrsonnet_macros::builtin]
509fn builtin_trace(s: State, loc: CallLocation, str: IStr, rest: Any) -> Result<Any> {513fn builtin_trace(s: State, loc: CallLocation, str: IStr, rest: Any) -> Result<Any> {
510 eprint!("TRACE:");514 eprint!("TRACE:");
511 if let Some(loc) = loc.0 {515 if let Some(loc) = loc.0 {
512 let locs = s.map_source_locations(&loc.0, &[loc.1]);516 let locs = s.map_source_locations(loc.0.clone(), &[loc.1]);
513 eprint!(517 eprint!(" {}:{}", loc.0.short_display(), locs[0].line);
514 " {}:{}",
515 loc.0.file_name().unwrap().to_str().unwrap(),
516 locs[0].line
517 );
518 }518 }
519 eprintln!(" {}", str);519 eprintln!(" {}", str);
520 Ok(rest) as Result<Any>520 Ok(rest) as Result<Any>
521}521}
522522
523#[jrsonnet_macros::builtin]523#[jrsonnet_macros::builtin]
524fn builtin_base64(input: Either![Bytes, IStr]) -> Result<String> {524fn builtin_base64(input: Either![IBytes, IStr]) -> Result<String> {
525 use Either2::*;525 use Either2::*;
526 Ok(match input {526 Ok(match input {
527 A(a) => base64::encode(a.0),527 A(a) => base64::encode(a.as_slice()),
528 B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),528 B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),
529 })529 })
530}530}
531531
532#[jrsonnet_macros::builtin]532#[jrsonnet_macros::builtin]
533fn builtin_base64_decode_bytes(input: IStr) -> Result<Bytes> {533fn builtin_base64_decode_bytes(input: IStr) -> Result<IBytes> {
534 Ok(Bytes(534 Ok(base64::decode(&input.as_bytes())
535 base64::decode(&input.as_bytes())
536 .map_err(|_| RuntimeError("bad base64".into()))?535 .map_err(|_| RuntimeError("bad base64".into()))?
537 .into(),536 .as_slice()
538 ))537 .into())
539}538}
540539
541#[jrsonnet_macros::builtin]540#[jrsonnet_macros::builtin]
modifiedcrates/jrsonnet-evaluator/src/trace/location.rsdiffbeforeafterboth
24}24}
2525
26#[allow(clippy::module_name_repetitions)]26#[allow(clippy::module_name_repetitions)]
27pub fn offset_to_location(file: &str, offsets: &[usize]) -> Vec<CodeLocation> {27pub fn offset_to_location(file: &str, offsets: &[u32]) -> Vec<CodeLocation> {
28 if offsets.is_empty() {28 if offsets.is_empty() {
29 return vec![];29 return vec![];
30 }30 }
59 {59 {
60 column += 1;60 column += 1;
61 match offset_map.last() {61 match offset_map.last() {
62 Some(x) if x.0 == pos => {62 Some(x) if x.0 == pos as u32 => {
63 let out_idx = x.1;63 let out_idx = x.1;
64 with_no_known_line_ending.push(out_idx);64 with_no_known_line_ending.push(out_idx);
65 out[out_idx].offset = pos;65 out[out_idx].offset = pos;
79 }79 }
80 this_line_offset = pos + 1;80 this_line_offset = pos + 1;
8181
82 if pos == max_offset + 1 {82 if pos == max_offset as usize + 1 {
83 break;83 break;
84 }84 }
85 }85 }
modifiedcrates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth
22
3use std::path::{Path, PathBuf};3use std::path::{Path, PathBuf};
44
5use jrsonnet_parser::Source;
5pub use location::*;6pub use location::*;
67
7use crate::{error::Error, LocError, State};8use crate::{error::Error, LocError, State};
56) -> Result<(), std::fmt::Error> {57) -> Result<(), std::fmt::Error> {
57 if start.line == end.line {58 if start.line == end.line {
58 if start.column == end.column {59 if start.column == end.column {
59 write!(out, "{}:{}", start.line, end.column - 1)?;60 write!(out, "{}:{}", start.line, end.column.saturating_sub(1))?;
60 } else {61 } else {
61 write!(out, "{}:{}-{}", start.line, start.column - 1, end.column)?;62 write!(out, "{}:{}-{}", start.line, start.column - 1, end.column)?;
62 }63 }
96 use std::fmt::Write;97 use std::fmt::Write;
9798
98 writeln!(out)?;99 writeln!(out)?;
99 let mut n = self.resolver.resolve(path);100 let mut n = match path.repr() {
101 Ok(r) => self.resolver.resolve(r),
102 Err(v) => v.to_string(),
103 };
100 let mut offset = error.location.offset;104 let mut offset = error.location.offset;
101 let is_eof = if offset >= source_code.len() {105 let is_eof = if offset >= source_code.len() {
102 offset = source_code.len().saturating_sub(1);106 offset = source_code.len().saturating_sub(1);
103 true107 true
104 } else {108 } else {
105 false109 false
106 };110 };
107 let mut location = offset_to_location(source_code, &[offset])111 let mut location = offset_to_location(source_code, &[offset as u32])
108 .into_iter()112 .into_iter()
109 .next()113 .next()
110 .unwrap();114 .unwrap();
125 use std::fmt::Write;129 use std::fmt::Write;
126 #[allow(clippy::option_if_let_else)]130 #[allow(clippy::option_if_let_else)]
127 if let Some(location) = location {131 if let Some(location) = location {
128 let mut resolved_path = self.resolver.resolve(&location.0);132 let mut resolved_path = match location.0.repr() {
133 Ok(r) => self.resolver.resolve(r),
134 Err(v) => v.to_string(),
135 };
129 // TODO: Process all trace elements first136 // TODO: Process all trace elements first
130 let location = s.map_source_locations(&location.0, &[location.1, location.2]);137 let location =
138 s.map_source_locations(location.0.clone(), &[location.1, location.2]);
131 write!(resolved_path, ":").unwrap();139 write!(resolved_path, ":").unwrap();
132 print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();140 print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();
133 write!(resolved_path, ":").unwrap();141 write!(resolved_path, ":").unwrap();
176 writeln!(out)?;184 writeln!(out)?;
177 let desc = &item.desc;185 let desc = &item.desc;
178 if let Some(source) = &item.location {186 if let Some(source) = &item.location {
179 let start_end = s.map_source_locations(&source.0, &[source.1, source.2]);187 let start_end = s.map_source_locations(source.0.clone(), &[source.1, source.2]);
188 let resolved_path = match source.0.repr() {
189 Ok(r) => r.display().to_string(),
190 Err(v) => v.to_string(),
191 };
180192
181 write!(193 write!(
182 out,194 out,
183 " at {} ({}:{}:{})",195 " at {} ({}:{}:{})",
184 desc,196 desc, resolved_path, start_end[0].line, start_end[0].column,
185 source.0.to_str().unwrap(),
186 start_end[0].line,
187 start_end[0].column,
188 )?;197 )?;
216 {225 {
217 writeln!(out)?;226 writeln!(out)?;
218 let offset = error.location.offset;227 let offset = error.location.offset;
219 let location = offset_to_location(source_code, &[offset])228 let location = offset_to_location(source_code, &[offset as u32])
220 .into_iter()229 .into_iter()
221 .next()230 .next()
222 .unwrap();231 .unwrap();
237 writeln!(out)?;246 writeln!(out)?;
238 let desc = &item.desc;247 let desc = &item.desc;
239 if let Some(source) = &item.location {248 if let Some(source) = &item.location {
240 let start_end = s.map_source_locations(&source.0, &[source.1, source.2]);249 let start_end = s.map_source_locations(source.0.clone(), &[source.1, source.2]);
241 self.print_snippet(250 self.print_snippet(
242 out,251 out,
243 &s.get_source(&source.0).unwrap(),252 &s.get_source(source.0.clone()).unwrap(),
244 &source.0,253 &source.0,
245 &start_end[0],254 &start_end[0],
246 &start_end[1],255 &start_end[1],
259 &self,268 &self,
260 out: &mut dyn std::fmt::Write,269 out: &mut dyn std::fmt::Write,
261 source: &str,270 source: &str,
262 origin: &Path,271 origin: &Source,
263 start: &CodeLocation,272 start: &CodeLocation,
264 end: &CodeLocation,273 end: &CodeLocation,
265 desc: &str,274 desc: &str,
275 .take(end.line_end_offset - end.line_start_offset)284 .take(end.line_end_offset - end.line_start_offset)
276 .collect();285 .collect();
277286
278 let origin = self.resolver.resolve(origin);287 let origin = match origin.repr() {
288 Ok(r) => self.resolver.resolve(r),
289 Err(v) => v.to_string(),
290 };
279 let snippet = Snippet {291 let snippet = Snippet {
280 opt: FormatOptions {292 opt: FormatOptions {
281 color: true,293 color: true,
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
1use std::{ops::Deref, rc::Rc};1use std::ops::Deref;
22
3use gcmodule::Cc;3use gcmodule::Cc;
4use jrsonnet_interner::IStr;4use jrsonnet_interner::{IBytes, IStr};
5pub use jrsonnet_macros::Typed;5pub use jrsonnet_macros::Typed;
6use jrsonnet_types::{ComplexValType, ValType};6use jrsonnet_types::{ComplexValType, ValType};
77
302 }302 }
303}303}
304304
305/// Specialization305/// Specialization
306pub struct Bytes(pub Rc<[u8]>);
307
308impl Typed for Bytes {306impl Typed for IBytes {
309 const TYPE: &'static ComplexValType =307 const TYPE: &'static ComplexValType =
310 &ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));308 &ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));
311309
312 fn into_untyped(value: Self, _: State) -> Result<Val> {310 fn into_untyped(value: Self, _: State) -> Result<Val> {
313 Ok(Val::Arr(ArrValue::Bytes(value.0)))311 Ok(Val::Arr(ArrValue::Bytes(value)))
314 }312 }
315313
316 fn from_untyped(value: Val, s: State) -> Result<Self> {314 fn from_untyped(value: Val, s: State) -> Result<Self> {
317 if let Val::Arr(ArrValue::Bytes(bytes)) = value {315 if let Val::Arr(ArrValue::Bytes(bytes)) = value {
318 return Ok(Self(bytes));316 return Ok(bytes);
319 }317 }
320 <Self as Typed>::TYPE.check(s.clone(), &value)?;318 <Self as Typed>::TYPE.check(s.clone(), &value)?;
321 match value {319 match value {
325 let r = e?;323 let r = e?;
326 out.push(u8::from_untyped(r, s.clone())?);324 out.push(u8::from_untyped(r, s.clone())?);
327 }325 }
328 Ok(Self(out.into()))326 Ok(out.as_slice().into())
329 }327 }
330 _ => unreachable!(),328 _ => unreachable!(),
331 }329 }
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
1use std::{cell::RefCell, fmt::Debug, rc::Rc};1use std::{cell::RefCell, fmt::Debug, rc::Rc};
22
3use gcmodule::{Cc, Trace};3use gcmodule::{Cc, Trace};
4use jrsonnet_interner::IStr;4use jrsonnet_interner::{IBytes, IStr};
5use jrsonnet_types::ValType;5use jrsonnet_types::ValType;
66
7use crate::{7use crate::{
186#[derive(Debug, Clone, Trace)]187#[derive(Debug, Clone, Trace)]
187#[force_tracking]188#[force_tracking]
188pub enum ArrValue {189pub enum ArrValue {
189 Bytes(#[skip_trace] Rc<[u8]>),190 Bytes(#[skip_trace] IBytes),
190 Lazy(Cc<Vec<Thunk<Val>>>),191 Lazy(Cc<Vec<Thunk<Val>>>),
191 Eager(Cc<Vec<Val>>),192 Eager(Cc<Vec<Val>>),
192 Extended(Box<(Self, Self)>),193 Extended(Box<(Self, Self)>),
195 Reversed(Box<Self>),196 Reversed(Box<Self>),
196}197}
198
199#[cfg(target_pointer_width = "64")]
200static_assertions::assert_eq_size!(ArrValue, [u8; 16]);
201
197impl ArrValue {202impl ArrValue {
198 pub fn new_eager() -> Self {203 pub fn new_eager() -> Self {
465 Func(FuncVal),470 Func(FuncVal),
466}471}
472
473#[cfg(target_pointer_width = "64")]
474static_assertions::assert_eq_size!(Val, [u8; 32]);
467475
468impl Val {476impl Val {
469 pub const fn as_bool(&self) -> Option<bool> {477 pub const fn as_bool(&self) -> Option<bool> {
modifiedcrates/jrsonnet-evaluator/tests/as_native.rsdiffbeforeafterboth
1use std::path::PathBuf;
2
3use jrsonnet_evaluator::{error::Result, State};1use jrsonnet_evaluator::{error::Result, State};
42
9 let s = State::default();7 let s = State::default();
10 s.with_stdlib();8 s.with_stdlib();
119
12 let val = s.evaluate_snippet_raw(PathBuf::new().into(), r#"function(a, b) a + b"#.into())?;10 let val = s.evaluate_snippet("snip".to_owned(), r#"function(a, b) a + b"#.into())?;
13 let func = val.as_func().expect("this is function");11 let func = val.as_func().expect("this is function");
1412
15 let native = func.into_native::<((u32, u32), u32)>();13 let native = func.into_native::<((u32, u32), u32)>();
modifiedcrates/jrsonnet-evaluator/tests/builtin.rsdiffbeforeafterboth
1mod common;1mod common;
2
3use std::path::PathBuf;
42
5use gcmodule::Cc;3use gcmodule::Cc;
6use jrsonnet_evaluator::{4use jrsonnet_evaluator::{
27 CallLocation::native(),25 CallLocation::native(),
28 &(),26 &(),
29 )?,27 )?,
30 s.clone(),28 s,
31 )?;29 )?;
3230
33 ensure_eq!(v, 1);31 ensure_eq!(v, 1);
48 Val::Func(FuncVal::StaticBuiltin(native_add::INST)),46 Val::Func(FuncVal::StaticBuiltin(native_add::INST)),
49 );47 );
5048
51 let v = s.evaluate_snippet_raw(49 let v = s.evaluate_snippet(
52 PathBuf::new().into(),50 "snip".to_owned(),
53 "51 "
54 assert nativeAdd(1, 2) == 3;52 assert nativeAdd(1, 2) == 3;
55 assert nativeAdd(100, 200) == 300;53 assert nativeAdd(100, 200) == 300;
56 null54 null
57 "55 "
58 .into(),56 .into(),
59 )?;57 )?;
60 ensure_val_eq!(s.clone(), v, Val::Null);58 ensure_val_eq!(s, v, Val::Null);
61 Ok(())59 Ok(())
62}60}
6361
82 Val::Func(FuncVal::StaticBuiltin(curry_add::INST)),80 Val::Func(FuncVal::StaticBuiltin(curry_add::INST)),
83 );81 );
8482
85 let v = s.evaluate_snippet_raw(83 let v = s.evaluate_snippet(
86 PathBuf::new().into(),84 "snip".to_owned(),
87 "85 "
88 local a = curryAdd(1);86 local a = curryAdd(1);
89 local b = curryAdd(4);87 local b = curryAdd(4);
97 "95 "
98 .into(),96 .into(),
99 )?;97 )?;
100 ensure_val_eq!(s.clone(), v, Val::Null);98 ensure_val_eq!(s, v, Val::Null);
101 Ok(())99 Ok(())
102}100}
103101
modifiedcrates/jrsonnet-evaluator/tests/golden.rsdiffbeforeafterboth
20 common::with_test(&s);20 common::with_test(&s);
21 s.set_import_resolver(Box::new(FileImportResolver::default()));21 s.set_import_resolver(Box::new(FileImportResolver::default()));
2222
23 let v = match s.evaluate_file_raw(file) {23 let v = match s.import(file.to_owned()) {
24 Ok(v) => v,24 Ok(v) => v,
25 Err(e) => return s.stringify_err(&e),25 Err(e) => return s.stringify_err(&e),
26 };26 };
modifiedcrates/jrsonnet-evaluator/tests/golden/issue23.jsonnet.goldendiffbeforeafterboth
1stack overflow, try to reduce recursion, or set --max-stack to bigger value1infinite recursion detected
2 issue23.jsonnet:1:1-26: import "issue23.jsonnet"2 issue23.jsonnet:1:1-26: import "/home/lach/build/jrsonnet/crates/jrsonnet-evaluator/tests/golden/issue23.jsonnet"
3 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
4 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
5 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
6 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
7 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
8 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
9 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
10 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
11 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
12 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
13 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
14 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
15 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
16 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
17 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
18 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
19 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
20 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
21 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
22 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
23 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
24 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
25 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
26 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
27 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
28 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
29 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
30 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
31 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
32 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
33 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
34 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
35 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
36 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
37 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
38 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
39 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
40 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
41 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
42 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
43 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
44 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
45 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
46 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
47 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
48 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
49 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
50 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
51 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
52 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
53 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
54 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
55 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
56 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
57 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
58 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
59 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
60 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
61 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
62 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
63 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
64 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
65 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
66 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
67 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
68 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
69 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
70 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
71 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
72 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
73 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
74 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
75 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
76 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
77 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
78 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
79 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
80 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
81 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
82 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
83 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
84 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
85 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
86 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
87 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
88 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
89 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
90 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
91 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
92 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
93 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
94 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
95 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
96 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
97 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
98 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
99 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
100 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
101 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
102 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
103 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
104 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
105 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
106 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
107 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
108 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
109 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
110 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
111 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
112 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
113 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
114 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
115 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
116 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
117 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
118 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
119 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
120 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
121 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
122 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
123 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
124 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
125 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
126 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
127 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
128 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
129 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
130 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
131 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
132 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
133 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
134 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
135 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
136 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
137 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
138 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
139 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
140 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
141 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
142 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
143 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
144 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
145 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
146 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
147 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
148 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
149 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
150 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
151 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
152 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
153 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
154 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
155 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
156 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
157 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
158 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
159 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
160 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
161 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
162 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
163 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
164 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
165 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
166 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
167 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
168 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
169 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
170 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
171 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
172 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
173 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
174 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
175 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
176 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
177 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
178 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
179 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
180 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
181 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
182 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
183 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
184 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
185 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
186 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
187 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
188 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
189 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
190 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
191 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
192 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
193 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
194 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
195 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
196 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
197 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
198 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
199 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
200 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
201 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
202 issue23.jsonnet:1:1-26: import "issue23.jsonnet"
modifiedcrates/jrsonnet-evaluator/tests/golden/missing_binding.jsonnet.goldendiffbeforeafterboth
1variable is not defined: a1runtime error: variable is not defined: a
2There is variable(s) with similar names present: std, test
2 missing_binding.jsonnet:1:1-3: variable <a> access3 missing_binding.jsonnet:1:1-3: variable <a> access
modifiedcrates/jrsonnet-evaluator/tests/sanity.rsdiffbeforeafterboth
1use std::path::PathBuf;
2
3use jrsonnet_evaluator::{error::Result, throw_runtime, State, Val};1use jrsonnet_evaluator::{error::Result, throw_runtime, State, Val};
42
9 let s = State::default();7 let s = State::default();
10 s.with_stdlib();8 s.with_stdlib();
119
12 let v = s.evaluate_snippet_raw(PathBuf::new().into(), "assert 1 == 1: 'fail'; null".into())?;10 let v = s.evaluate_snippet("snip".to_owned(), "assert 1 == 1: 'fail'; null".into())?;
13 ensure_val_eq!(s.clone(), v, Val::Null);11 ensure_val_eq!(s, v, Val::Null);
14 let v = s.evaluate_snippet_raw(PathBuf::new().into(), "std.assertEqual(1, 1)".into())?;12 let v = s.evaluate_snippet("snip".to_owned(), "std.assertEqual(1, 1)".into())?;
15 ensure_val_eq!(s.clone(), v, Val::Bool(true));13 ensure_val_eq!(s, v, Val::Bool(true));
1614
17 Ok(())15 Ok(())
18}16}
23 s.with_stdlib();21 s.with_stdlib();
2422
25 {23 {
26 let e = match s24 let e = match s.evaluate_snippet("snip".to_owned(), "assert 1 == 2: 'fail'; null".into()) {
27 .evaluate_snippet_raw(PathBuf::new().into(), "assert 1 == 2: 'fail'; null".into())
28 {
29 Ok(_) => throw_runtime!("assertion should fail"),25 Ok(_) => throw_runtime!("assertion should fail"),
30 Err(e) => e,26 Err(e) => e,
33 ensure!(e.starts_with("assert failed: fail\n"));29 ensure!(e.starts_with("assert failed: fail\n"));
34 }30 }
35 {31 {
36 let e = match s.evaluate_snippet_raw(PathBuf::new().into(), "std.assertEqual(1, 2)".into())32 let e = match s.evaluate_snippet("snip".to_owned(), "std.assertEqual(1, 2)".into()) {
37 {
38 Ok(_) => throw_runtime!("assertion should fail"),33 Ok(_) => throw_runtime!("assertion should fail"),
39 Err(e) => e,34 Err(e) => e,
modifiedcrates/jrsonnet-evaluator/tests/suite.rsdiffbeforeafterboth
20 common::with_test(&s);20 common::with_test(&s);
21 s.set_import_resolver(Box::new(FileImportResolver::default()));21 s.set_import_resolver(Box::new(FileImportResolver::default()));
2222
23 match s.evaluate_file_raw(file) {23 match s.import(file.to_owned()) {
24 Ok(Val::Bool(true)) => {}24 Ok(Val::Bool(true)) => {}
25 Ok(Val::Bool(false)) => panic!("test {} returned false", file.display()),25 Ok(Val::Bool(false)) => panic!("test {} returned false", file.display()),
26 Ok(_) => panic!("test {} returned wrong type as result", file.display()),26 Ok(_) => panic!("test {} returned wrong type as result", file.display()),
modifiedcrates/jrsonnet-evaluator/tests/typed_obj.rsdiffbeforeafterboth
1mod common;1mod common;
22
3use std::{fmt::Debug, path::PathBuf};3use std::fmt::Debug;
44
5use jrsonnet_evaluator::{error::Result, typed::Typed, State};5use jrsonnet_evaluator::{error::Result, typed::Typed, State};
66
25 let s = State::default();25 let s = State::default();
26 s.with_stdlib();26 s.with_stdlib();
27 let a = A::from_untyped(27 let a = A::from_untyped(
28 s.evaluate_snippet_raw(PathBuf::new().into(), "{a: 1, b: 2}".into())?,28 s.evaluate_snippet("snip".to_owned(), "{a: 1, b: 2}".into())?,
29 s.clone(),29 s.clone(),
30 )?;30 )?;
31 ensure_eq!(a, A { a: 1, b: 2 });31 ensure_eq!(a, A { a: 1, b: 2 });
32 test_roundtrip(a.clone(), s.clone())?;32 test_roundtrip(a, s)?;
33 Ok(())33 Ok(())
34}34}
3535
45 let s = State::default();45 let s = State::default();
46 s.with_stdlib();46 s.with_stdlib();
47 let b = B::from_untyped(47 let b = B::from_untyped(
48 s.evaluate_snippet_raw(PathBuf::new().into(), "{a: 1, c: 2}".into())?,48 s.evaluate_snippet("snip".to_owned(), "{a: 1, c: 2}".into())?,
49 s.clone(),49 s.clone(),
50 )?;50 )?;
51 ensure_eq!(b, B { a: 1, b: 2 });51 ensure_eq!(b, B { a: 1, b: 2 });
52 ensure_eq!(52 ensure_eq!(
53 &B::into_untyped(b.clone(), s.clone())?.to_string(s.clone())? as &str,53 &B::into_untyped(b.clone(), s.clone())?.to_string(s.clone())? as &str,
54 r#"{"a": 1, "c": 2}"#,54 r#"{"a": 1, "c": 2}"#,
55 );55 );
56 test_roundtrip(b.clone(), s.clone())?;56 test_roundtrip(b, s)?;
57 Ok(())57 Ok(())
58}58}
5959
77 let s = State::default();77 let s = State::default();
78 s.with_stdlib();78 s.with_stdlib();
79 let obj = Object::from_untyped(79 let obj = Object::from_untyped(
80 s.evaluate_snippet_raw(80 s.evaluate_snippet(
81 PathBuf::new().into(),81 "snip".to_owned(),
82 "{apiVersion: 'ver', kind: 'kind', b: 2}".into(),82 "{apiVersion: 'ver', kind: 'kind', b: 2}".into(),
83 )?,83 )?,
84 s.clone(),84 s.clone(),
97 &Object::into_untyped(obj.clone(), s.clone())?.to_string(s.clone())? as &str,97 &Object::into_untyped(obj.clone(), s.clone())?.to_string(s.clone())? as &str,
98 r#"{"apiVersion": "ver", "b": 2, "kind": "kind"}"#,98 r#"{"apiVersion": "ver", "b": 2, "kind": "kind"}"#,
99 );99 );
100 test_roundtrip(obj.clone(), s.clone())?;100 test_roundtrip(obj, s)?;
101 Ok(())101 Ok(())
102}102}
103103
112 let s = State::default();112 let s = State::default();
113 s.with_stdlib();113 s.with_stdlib();
114 let c = C::from_untyped(114 let c = C::from_untyped(
115 s.evaluate_snippet_raw(PathBuf::new().into(), "{a: 1, b: 2}".into())?,115 s.evaluate_snippet("snip".to_owned(), "{a: 1, b: 2}".into())?,
116 s.clone(),116 s.clone(),
117 )?;117 )?;
118 ensure_eq!(c, C { a: Some(1), b: 2 });118 ensure_eq!(c, C { a: Some(1), b: 2 });
119 ensure_eq!(119 ensure_eq!(
120 &C::into_untyped(c.clone(), s.clone())?.to_string(s.clone())? as &str,120 &C::into_untyped(c.clone(), s.clone())?.to_string(s.clone())? as &str,
121 r#"{"a": 1, "b": 2}"#,121 r#"{"a": 1, "b": 2}"#,
122 );122 );
123 test_roundtrip(c.clone(), s.clone())?;123 test_roundtrip(c, s)?;
124 Ok(())124 Ok(())
125}125}
126126
129 let s = State::default();129 let s = State::default();
130 s.with_stdlib();130 s.with_stdlib();
131 let c = C::from_untyped(131 let c = C::from_untyped(
132 s.evaluate_snippet_raw(PathBuf::new().into(), "{b: 2}".into())?,132 s.evaluate_snippet("snip".to_owned(), "{b: 2}".into())?,
133 s.clone(),133 s.clone(),
134 )?;134 )?;
135 ensure_eq!(c, C { a: None, b: 2 });135 ensure_eq!(c, C { a: None, b: 2 });
136 ensure_eq!(136 ensure_eq!(
137 &C::into_untyped(c.clone(), s.clone())?.to_string(s.clone())? as &str,137 &C::into_untyped(c.clone(), s.clone())?.to_string(s.clone())? as &str,
138 r#"{"b": 2}"#,138 r#"{"b": 2}"#,
139 );139 );
140 test_roundtrip(c.clone(), s.clone())?;140 test_roundtrip(c, s)?;
141 Ok(())141 Ok(())
142}142}
143143
158 let s = State::default();158 let s = State::default();
159 s.with_stdlib();159 s.with_stdlib();
160 let d = D::from_untyped(160 let d = D::from_untyped(
161 s.evaluate_snippet_raw(PathBuf::new().into(), "{b: 2, v:1}".into())?,161 s.evaluate_snippet("snip".to_owned(), "{b: 2, v:1}".into())?,
162 s.clone(),162 s.clone(),
163 )?;163 )?;
164 ensure_eq!(164 ensure_eq!(
172 &D::into_untyped(d.clone(), s.clone())?.to_string(s.clone())? as &str,172 &D::into_untyped(d.clone(), s.clone())?.to_string(s.clone())? as &str,
173 r#"{"b": 2, "v": 1}"#,173 r#"{"b": 2, "v": 1}"#,
174 );174 );
175 test_roundtrip(d.clone(), s.clone())?;175 test_roundtrip(d, s)?;
176 Ok(())176 Ok(())
177}177}
178178
181 let s = State::default();181 let s = State::default();
182 s.with_stdlib();182 s.with_stdlib();
183 let d = D::from_untyped(183 let d = D::from_untyped(
184 s.evaluate_snippet_raw(PathBuf::new().into(), "{b: 2, v: '1'}".into())?,184 s.evaluate_snippet("snip".to_owned(), "{b: 2, v: '1'}".into())?,
185 s.clone(),185 s.clone(),
186 )?;186 )?;
187 ensure_eq!(d, D { e: None, b: 2 });187 ensure_eq!(d, D { e: None, b: 2 });
188 ensure_eq!(188 ensure_eq!(
189 &D::into_untyped(d.clone(), s.clone())?.to_string(s.clone())? as &str,189 &D::into_untyped(d.clone(), s.clone())?.to_string(s.clone())? as &str,
190 r#"{"b": 2}"#,190 r#"{"b": 2}"#,
191 );191 );
192 test_roundtrip(d.clone(), s.clone())?;192 test_roundtrip(d, s)?;
193 Ok(())193 Ok(())
194}194}
195195
modifiedcrates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth
128 IStr(self.0.clone())128 IStr(self.0.clone())
129 }129 }
130
131 #[must_use]
132 pub fn as_slice(&self) -> &[u8] {
133 self.0.as_slice()
134 }
130}135}
131136
132impl Deref for IBytes {137impl Deref for IBytes {
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
362362
363#[cfg(test)]363#[cfg(test)]
364pub mod tests {364pub mod tests {
365 use std::path::PathBuf;365 use std::borrow::Cow;
366366
367 use BinaryOpType::*;367 use BinaryOpType::*;
368368
374 parse(374 parse(
375 $s,375 $s,
376 &ParserSettings {376 &ParserSettings {
377 file_name: Source::new(PathBuf::from("test.jsonnet")).unwrap(),377 file_name: Source::new_virtual(Cow::Borrowed("<test>")),
378 },378 },
379 )379 )
380 .unwrap()380 .unwrap()
385 ($expr:expr, $from:expr, $to:expr$(,)?) => {385 ($expr:expr, $from:expr, $to:expr$(,)?) => {
386 LocExpr(386 LocExpr(
387 std::rc::Rc::new($expr),387 std::rc::Rc::new($expr),
388 ExprLocation(388 ExprLocation(Source::new_virtual(Cow::Borrowed("<test>")), $from, $to),
389 Source::new(PathBuf::from("test.jsonnet")).unwrap(),
390 $from,
391 $to,
392 ),
393 )389 )
394 };390 };
727 fn add_location_info_to_all_sub_expressions() {723 fn add_location_info_to_all_sub_expressions() {
728 use Expr::*;724 use Expr::*;
729725
730 let file_name = Source::new(PathBuf::from("test.jsonnet")).unwrap();726 let file_name = Source::new_virtual(Cow::Borrowed("<test>"));
731 let expr = parse(727 let expr = parse(
732 "{} { local x = 1, x: x } + {}",728 "{} { local x = 1, x: x } + {}",
733 &ParserSettings {729 &ParserSettings { file_name },
734 file_name: file_name.clone(),
735 },
736 )730 )
737 .unwrap();731 .unwrap();