difftreelog
refactor rework layout and path handling
in: master
32 files changed
bindings/jsonnet/src/import.rsdiffbeforeafterboth10 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};151416use 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 }757476 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() {bindings/jsonnet/src/lib.rsdiffbeforeafterboth111) -> *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 vm114 .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 vm143 .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 vm188 .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 vm215 .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 vm258 .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 vm285 .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))bindings/jsonnet/src/native.rsdiffbeforeafterboth1use 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};758use 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())));cmds/jrsonnet/src/main.rsdiffbeforeafterboth120 opts.manifest.configure(s)?;120 opts.manifest.configure(s)?;121121122 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 };135132136 let val = s.with_tla(val)?;133 let val = s.with_tla(val)?;crates/jrsonnet-cli/src/ext.rsdiffbeforeafterboth108 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 }crates/jrsonnet-cli/src/tla.rsdiffbeforeafterboth55 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 }crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth28jrsonnet-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"313332md5 = "0.7.0"34md5 = "0.7.0"33base64 = "0.13.0"35base64 = "0.13.0"crates/jrsonnet-evaluator/build.rsdiffbeforeafterboth1use 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};728use 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;11612fn 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");crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth1use std::{1use std::{fmt::Debug, path::PathBuf};2 fmt::Debug,3 path::{Path, PathBuf},4 rc::Rc,5};627use 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;12885 StandaloneSuper,81 StandaloneSuper,868287 #[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>,crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth452 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 },617617618 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 = tmp623 .path()624 .map(|p| {625 let mut p = p.to_owned();626 p.pop();627 p628 })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}645644crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth47 }47 }48}48}494950#[derive(Clone)]50pub enum TlaArg {51pub enum TlaArg {51 String(IStr),52 String(IStr),52 Code(LocExpr),53 Code(LocExpr),crates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth1use std::{borrow::Cow, path::Path, rc::Rc};1use std::borrow::Cow;223use gcmodule::Trace;3use gcmodule::Trace;4451 &self.params51 &self.params52 }52 }535354 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}636364pub 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}6767crates/jrsonnet-evaluator/src/gc.rsdiffbeforeafterboth1/// Macros to help deal with Gc1/// Macros to help deal with Gc2use 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};889use gcmodule::{Trace, Tracer};9use gcmodule::{Trace, Tracer};10use hashbrown::HashMap;10use rustc_hash::{FxHashMap, FxHashSet};11use rustc_hash::{FxHashSet, FxHasher};111212/// 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 stable115 }116 }116}117}117118118#[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>>;145145146 fn deref(&self) -> &Self::Target {146 fn deref(&self) -> &Self::Target {147 &self.0147 &self.0crates/jrsonnet-evaluator/src/import.rsdiffbeforeafterboth1use 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};9710use fs::File;8use fs::File;11use jrsonnet_interner::IStr;12913use 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 correspond21 /// 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>;242125 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;22 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;2627 /// 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 }3233 /// 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 }372338 /// # Safety24 /// # Safety39 ///25 ///46/// Dummy resolver, can't resolve/load any file32/// Dummy resolver, can't resolve/load any file47pub 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 }523873 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()))crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth38pub mod val;38pub mod val;393940use 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 preserved97 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.native101 pub ext_natives: HashMap<IStr, Cc<TraceBox<dyn Builtin>>>,104 pub ext_natives: HashMap<IStr, Cc<TraceBox<dyn Builtin>>>,102 /// TLA vars105 /// TLA vars141 stack_generation: usize,144 stack_generation: usize,142145143 breakpoints: Breakpoints,146 breakpoints: Breakpoints,147144 /// 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 stacktraces145 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 name147 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>,149158150pub 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}155181156#[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>);199225200impl 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())?;215230216 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 .1244 }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.bytes252 .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);218264219 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 .1271 }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.string279 .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);227290228 /// 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 .1304 }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.bytes313 .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 evaluation343 drop(data);344 let res = evaluate(self.clone(), self.create_default_context(), &parsed);243345244 Ok(())346 let mut data = self.data_mut();347 let mut file = data.files.raw_entry_mut().from_key(&path);348349 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 }362246 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) => data367 .files248 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 }295296 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_map300 .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 .files311 .get_mut(name)312 .unwrap()313 .evaluated314 .replace(value.clone());315 }316 Ok(value)317 }318319 /// Adds standard library global variable (std) to this evaluator389 /// Adds standard library global variable (std) to this evaluator320 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();323324 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 = self331 .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 self335 }399 }506570507/// Raw methods evaluate passed values but don't perform TLA execution571/// Raw methods evaluate passed values but don't perform TLA execution508impl 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 snippet516 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 expression532 pub fn evaluate_expr_raw(&self, code: LocExpr) -> Result<Val> {533 evaluate(self.clone(), self.create_default_context(), &code)534 }535}590}536591537/// Settings utilities592/// Settings utilities538impl 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_vars597 .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_vars602 .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_vars621 .insert(name.into(), TlaArg::Code(parsed));549 Ok(())622 Ok(())550 }623 }551624559 .tla_vars632 .tla_vars560 .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_files651 .insert(source_name, code.to_owned());564 self.settings_mut()652 self.settings_mut()565 .tla_vars653 .tla_vars566 .insert(name, TlaArg::Code(parsed));654 .insert(name, TlaArg::Code(parsed));567 Ok(())655 Ok(())568 }656 }569657570 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_resolver573 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 }579663580 pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {664 pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {crates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth14pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);14pub struct LayeredHashMap(Cc<LayeredHashMapInternals>);151516impl 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 }2517 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 {crates/jrsonnet-evaluator/src/stdlib/expr.rsdiffbeforeafterboth1use std::path::PathBuf;1use std::borrow::Cow;223use jrsonnet_parser::{LocExpr, ParserSettings};3use jrsonnet_parser::{LocExpr, ParserSettings, Source};445thread_local! {5thread_local! {6 /// To avoid parsing again when issued from the same thread6 /// To avoid parsing again when issued from the same thread16 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()crates/jrsonnet-evaluator/src/stdlib/mod.rsdiffbeforeafterboth556use 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;111112use 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};365365366#[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(s370 .clone()369 .settings()371 .settings()370 .ext_vars372 .ext_vars371 .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}375379376#[jrsonnet_macros::builtin]380#[jrsonnet_macros::builtin]489}493}490494491#[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}495499496#[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(arr503 .cast_str()499 .map_err(|_| RuntimeError("bad utf8".into()))?504 .ok_or_else(|| RuntimeError("bad utf8".into()))?)500 .into())501}505}502506503#[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].line517 );518 }518 }519 eprintln!(" {}", str);519 eprintln!(" {}", str);520 Ok(rest) as Result<Any>520 Ok(rest) as Result<Any>521}521}522522523#[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}531531532#[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}540539541#[jrsonnet_macros::builtin]540#[jrsonnet_macros::builtin]crates/jrsonnet-evaluator/src/trace/location.rsdiffbeforeafterboth24}24}252526#[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;818182 if pos == max_offset + 1 {82 if pos == max_offset as usize + 1 {83 break;83 break;84 }84 }85 }85 }crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth223use std::path::{Path, PathBuf};3use std::path::{Path, PathBuf};445use jrsonnet_parser::Source;5pub use location::*;6pub use location::*;677use 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;979898 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 true104 } else {108 } else {105 false109 false106 };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 first130 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 };180192181 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();277286278 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,crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth1use std::{ops::Deref, rc::Rc};1use std::ops::Deref;223use 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};77302 }302 }303}303}304304305/// Specialization305/// Specialization306pub struct Bytes(pub Rc<[u8]>);307308impl 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)));311309312 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 }315313316 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 }crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth1use std::{cell::RefCell, fmt::Debug, rc::Rc};1use std::{cell::RefCell, fmt::Debug, rc::Rc};223use gcmodule::{Cc, Trace};3use gcmodule::{Cc, Trace};4use jrsonnet_interner::IStr;4use jrsonnet_interner::{IBytes, IStr};5use jrsonnet_types::ValType;5use jrsonnet_types::ValType;667use 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}198199#[cfg(target_pointer_width = "64")]200static_assertions::assert_eq_size!(ArrValue, [u8; 16]);201197impl ArrValue {202impl ArrValue {198 pub fn new_eager() -> Self {203 pub fn new_eager() -> Self {465 Func(FuncVal),470 Func(FuncVal),466}471}472473#[cfg(target_pointer_width = "64")]474static_assertions::assert_eq_size!(Val, [u8; 32]);467475468impl Val {476impl Val {469 pub const fn as_bool(&self) -> Option<bool> {477 pub const fn as_bool(&self) -> Option<bool> {crates/jrsonnet-evaluator/tests/as_native.rsdiffbeforeafterboth1use std::path::PathBuf;23use jrsonnet_evaluator::{error::Result, State};1use jrsonnet_evaluator::{error::Result, State};429 let s = State::default();7 let s = State::default();10 s.with_stdlib();8 s.with_stdlib();11912 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");141215 let native = func.into_native::<((u32, u32), u32)>();13 let native = func.into_native::<((u32, u32), u32)>();crates/jrsonnet-evaluator/tests/builtin.rsdiffbeforeafterboth1mod common;1mod common;23use std::path::PathBuf;425use 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 )?;323033 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 );504851 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 null57 "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}636182 Val::Func(FuncVal::StaticBuiltin(curry_add::INST)),80 Val::Func(FuncVal::StaticBuiltin(curry_add::INST)),83 );81 );848285 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}103101crates/jrsonnet-evaluator/tests/golden.rsdiffbeforeafterboth20 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()));222223 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 };crates/jrsonnet-evaluator/tests/golden/issue23.jsonnet.goldendiffbeforeafterboth1stack overflow, try to reduce recursion, or set --max-stack to bigger value1infinite recursion detected2 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"crates/jrsonnet-evaluator/tests/golden/missing_binding.jsonnet.goldendiffbeforeafterboth1variable is not defined: a1runtime error: variable is not defined: a2There is variable(s) with similar names present: std, test2 missing_binding.jsonnet:1:1-3: variable <a> access3 missing_binding.jsonnet:1:1-3: variable <a> accesscrates/jrsonnet-evaluator/tests/sanity.rsdiffbeforeafterboth1use std::path::PathBuf;23use jrsonnet_evaluator::{error::Result, throw_runtime, State, Val};1use jrsonnet_evaluator::{error::Result, throw_runtime, State, Val};429 let s = State::default();7 let s = State::default();10 s.with_stdlib();8 s.with_stdlib();11912 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));161417 Ok(())15 Ok(())18}16}23 s.with_stdlib();21 s.with_stdlib();242225 {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,crates/jrsonnet-evaluator/tests/suite.rsdiffbeforeafterboth20 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()));222223 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()),crates/jrsonnet-evaluator/tests/typed_obj.rsdiffbeforeafterboth1mod common;1mod common;223use std::{fmt::Debug, path::PathBuf};3use std::fmt::Debug;445use jrsonnet_evaluator::{error::Result, typed::Typed, State};5use jrsonnet_evaluator::{error::Result, typed::Typed, State};6625 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}353545 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}595977 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}103103112 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}126126129 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}143143158 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}178178181 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}195195crates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth128 IStr(self.0.clone())128 IStr(self.0.clone())129 }129 }130131 #[must_use]132 pub fn as_slice(&self) -> &[u8] {133 self.0.as_slice()134 }130}135}131136132impl Deref for IBytes {137impl Deref for IBytes {crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth362362363#[cfg(test)]363#[cfg(test)]364pub mod tests {364pub mod tests {365 use std::path::PathBuf;365 use std::borrow::Cow;366366367 use BinaryOpType::*;367 use BinaryOpType::*;368368374 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::*;729725730 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();