git.delta.rocks / jrsonnet / refs/commits / 74199ce77317

difftreelog

Merge remote-tracking branch 'origin/feature/importbin' into gcmodule

Yaroslav Bolyukin2022-04-20parents: #4f4be44 #be790e9.patch.diff
in: master

11 files changed

modifiedbindings/jsonnet/src/import.rsdiffbeforeafterboth
22
3use jrsonnet_evaluator::{3use jrsonnet_evaluator::{
4 error::{Error::*, Result},4 error::{Error::*, Result},
5 throw, EvaluationState, IStr, ImportResolver,5 throw, EvaluationState, ImportResolver,
6};6};
7use std::{7use std::{
8 any::Any,8 any::Any,
30 cb: JsonnetImportCallback,30 cb: JsonnetImportCallback,
31 ctx: *mut c_void,31 ctx: *mut c_void,
32
33 out: RefCell<HashMap<PathBuf, IStr>>,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<Rc<Path>> {
7574
76 Ok(found_here_buf.into())75 Ok(found_here_buf.into())
77 }76 }
78 fn load_file_contents(&self, resolved: &Path) -> Result<IStr> {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())
80 }79 }
80
124 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))124 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))
125 }125 }
126 }126 }
127 fn load_file_contents(&self, id: &Path) -> Result<IStr> {127 fn load_file_contents(&self, id: &Path) -> Result<Vec<u8>> {
128 let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.to_owned()))?;128 let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.to_owned()))?;
129 let mut out = String::new();129 let mut out = Vec::new();
130 file.read_to_string(&mut out)130 file.read_to_end(&mut out)
131 .map_err(|_e| ImportBadFileUtf8(id.to_owned()))?;131 .map_err(|e| ImportIo(e.to_string()))?;
132 Ok(out.into())132 Ok(out)
133 }133 }
134 unsafe fn as_any(&self) -> &dyn Any {134 unsafe fn as_any(&self) -> &dyn Any {
135 self135 self
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
1use crate::function::{CallLocation, StaticBuiltin};1use crate::function::{CallLocation, StaticBuiltin};
2use crate::typed::{Any, PositiveF64, VecVal, M1};2use crate::typed::{Any, Bytes, PositiveF64, VecVal, M1};
3use crate::{3use crate::{
4 builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},4 builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},
5 equals,5 equals,
447}447}
448448
449#[jrsonnet_macros::builtin]449#[jrsonnet_macros::builtin]
450fn builtin_encode_utf8(str: IStr) -> Result<VecVal> {450fn builtin_encode_utf8(str: IStr) -> Result<Bytes> {
451 Ok(VecVal(451 Ok(Bytes(str.bytes().map(|b| b).collect::<Vec<u8>>().into()))
452 str.bytes()
453 .map(|b| Val::Num(b as f64))
454 .collect::<Vec<Val>>(),
455 ))
456}452}
457453
458#[jrsonnet_macros::builtin]454#[jrsonnet_macros::builtin]
459fn builtin_decode_utf8(arr: Vec<u8>) -> Result<String> {455fn builtin_decode_utf8(arr: Bytes) -> Result<IStr> {
460 Ok(String::from_utf8(arr).map_err(|_| RuntimeError("bad utf8".into()))?)456 Ok(std::str::from_utf8(&arr.0)
457 .map_err(|_| RuntimeError("bad utf8".into()))?
458 .into())
461}459}
462460
463#[jrsonnet_macros::builtin]461#[jrsonnet_macros::builtin]
483}481}
484482
485#[jrsonnet_macros::builtin]483#[jrsonnet_macros::builtin]
486fn builtin_base64(input: Either![Vec<u8>, IStr]) -> Result<String> {484fn builtin_base64(input: Either![Bytes, IStr]) -> Result<String> {
487 use Either2::*;485 use Either2::*;
488 Ok(match input {486 Ok(match input {
489 A(a) => base64::encode(a),487 A(a) => base64::encode(a.0),
490 B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),488 B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),
491 })489 })
492}490}
493491
494#[jrsonnet_macros::builtin]492#[jrsonnet_macros::builtin]
495fn builtin_base64_decode_bytes(input: IStr) -> Result<Vec<u8>> {493fn builtin_base64_decode_bytes(input: IStr) -> Result<Bytes> {
496 Ok(base64::decode(&input.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?)494 Ok(Bytes(
495 base64::decode(&input.as_bytes())
496 .map_err(|_| RuntimeError("bad base64".into()))?
497 .into(),
498 ))
497}499}
498500
499#[jrsonnet_macros::builtin]501#[jrsonnet_macros::builtin]
modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
82 ResolvedFileNotFound(PathBuf),82 ResolvedFileNotFound(PathBuf),
83 #[error("imported file is not valid utf-8: {0:?}")]83 #[error("imported file is not valid utf-8: {0:?}")]
84 ImportBadFileUtf8(PathBuf),84 ImportBadFileUtf8(PathBuf),
85 #[error("import io error: {0}")]
86 ImportIo(String),
85 #[error("tried to import {1} from {0}, but imports is not supported")]87 #[error("tried to import {1} from {0}, but imports is not supported")]
86 ImportNotSupported(PathBuf, PathBuf),88 ImportNotSupported(PathBuf, PathBuf),
87 #[error(89 #[error(
modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
701 import_location.pop();701 import_location.pop();
702 Val::Str(with_state(|s| s.import_file_str(&import_location, path))?)702 Val::Str(with_state(|s| s.import_file_str(&import_location, path))?)
703 }703 }
704 ImportBin(path) => {
705 let tmp = loc.clone().0;
706 let mut import_location = tmp.to_path_buf();
707 import_location.pop();
708 let bytes = with_state(|s| s.import_file_bin(&import_location, path))?;
709 Val::Arr(ArrValue::Bytes(bytes))
710 }
704 })711 })
705}712}
706713
modifiedcrates/jrsonnet-evaluator/src/import.rsdiffbeforeafterboth
5use fs::File;5use fs::File;
6use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
7use std::fs;7use std::fs;
8use std::io::Read;
9use std::{8use std::{
10 any::Any,9 any::Any,
11 cell::RefCell,
12 collections::HashMap,
13 path::{Path, PathBuf},10 path::{Path, PathBuf},
14 rc::Rc,11 rc::Rc,
15};12};
13use std::{convert::TryFrom, io::Read};
1614
17/// Implements file resolution logic for `import` and `importStr`15/// Implements file resolution logic for `import` and `importStr`
18pub trait ImportResolver {16pub trait ImportResolver {
21 /// where `${vendor}` is a library path.19 /// where `${vendor}` is a library path.
22 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>>;20 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>>;
21
22 fn load_file_contents(&self, resolved: &Path) -> Result<Vec<u8>>;
2323
24 /// Reads file from filesystem, should be used only with path received from `resolve_file`24 /// Reads file from filesystem, should be used only with path received from `resolve_file`
25 fn load_file_contents(&self, resolved: &Path) -> Result<IStr>;25 fn load_file_str(&self, resolved: &Path) -> Result<IStr> {
26 Ok(IStr::try_from(&self.load_file_contents(resolved)? as &[u8])
27 .map_err(|_| ImportBadFileUtf8(resolved.to_path_buf()))?)
28 }
29
30 /// Reads file from filesystem, should be used only with path received from `resolve_file`
31 fn load_file_bin(&self, resolved: &Path) -> Result<Rc<[u8]>> {
32 Ok(self.load_file_contents(resolved)?.into())
33 }
2634
27 /// # Safety35 /// # Safety
28 ///36 ///
39 throw!(ImportNotSupported(from.into(), path.into()))47 throw!(ImportNotSupported(from.into(), path.into()))
40 }48 }
4149
42 fn load_file_contents(&self, _resolved: &Path) -> Result<IStr> {50 fn load_file_contents(&self, _resolved: &Path) -> Result<Vec<u8>> {
43 // Can be only caused by library direct consumer, not by supplied jsonnet
44 panic!("dummy resolver can't load any file")51 panic!("dummy resolver can't load any file")
45 }52 }
4653
79 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))86 throw!(ImportFileNotFound(from.to_owned(), path.to_owned()))
80 }87 }
81 }88 }
82 fn load_file_contents(&self, id: &Path) -> Result<IStr> {89 fn load_file_contents(&self, id: &Path) -> Result<Vec<u8>> {
83 let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.to_owned()))?;90 let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.to_owned()))?;
84 let mut out = String::new();91 let mut out = Vec::new();
85 file.read_to_string(&mut out)92 file.read_to_end(&mut out)
86 .map_err(|_e| ImportBadFileUtf8(id.to_owned()))?;93 .map_err(|e| ImportIo(e.to_string()))?;
87 Ok(out.into())94 Ok(out)
88 }95 }
89 unsafe fn as_any(&self) -> &dyn Any {96 unsafe fn as_any(&self) -> &dyn Any {
90 panic!("this resolver can't be used as any")97 panic!("this resolver can't be used as any")
91 }98 }
92}99}
93
94type ResolutionData = (PathBuf, PathBuf);
95
96/// Caches results of the underlying resolver
97pub struct CachingImportResolver {
98 resolution_cache: RefCell<HashMap<ResolutionData, Result<Rc<Path>>>>,
99 loading_cache: RefCell<HashMap<PathBuf, Result<IStr>>>,
100 inner: Box<dyn ImportResolver>,
101}
102impl ImportResolver for CachingImportResolver {
103 fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {
104 self.resolution_cache
105 .borrow_mut()
106 .entry((from.to_owned(), path.to_owned()))
107 .or_insert_with(|| self.inner.resolve_file(from, path))
108 .clone()
109 }
110
111 fn load_file_contents(&self, resolved: &Path) -> Result<IStr> {
112 self.loading_cache
113 .borrow_mut()
114 .entry(resolved.to_owned())
115 .or_insert_with(|| self.inner.load_file_contents(resolved))
116 .clone()
117 }
118 unsafe fn as_any(&self) -> &dyn Any {
119 panic!("this resolver can't be used as any")
120 }
121}
122100
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
118118
119 breakpoints: Breakpoints,119 breakpoints: Breakpoints,
120 /// Contains file source codes and evaluation results for imports and pretty-printed stacktraces120 /// Contains file source codes and evaluation results for imports and pretty-printed stacktraces
121 files: HashMap<Rc<Path>, FileData>,121 files: GcHashMap<Rc<Path>, FileData>,
122 str_files: HashMap<Rc<Path>, IStr>,122 str_files: GcHashMap<Rc<Path>, IStr>,
123 bin_files: GcHashMap<Rc<Path>, Rc<[u8]>>,
123}124}
124125
125pub struct FileData {126pub struct FileData {
280 return self.evaluate_loaded_file_raw(&file_path);281 return self.evaluate_loaded_file_raw(&file_path);
281 }282 }
282 }283 }
283 let contents = self.load_file_contents(&file_path)?;284 let contents = self.load_file_str(&file_path)?;
284 self.add_file(file_path.clone(), contents)?;285 self.add_file(file_path.clone(), contents)?;
285 self.evaluate_loaded_file_raw(&file_path)286 self.evaluate_loaded_file_raw(&file_path)
286 }287 }
287 pub(crate) fn import_file_str(&self, from: &Path, path: &Path) -> Result<IStr> {288 pub(crate) fn import_file_str(&self, from: &Path, path: &Path) -> Result<IStr> {
288 let path = self.resolve_file(from, path)?;289 let path = self.resolve_file(from, path)?;
289 if !self.data().str_files.contains_key(&path) {290 if !self.data().str_files.contains_key(&path) {
290 let file_str = self.load_file_contents(&path)?;291 let file_str = self.load_file_str(&path)?;
291 self.data_mut().str_files.insert(path.clone(), file_str);292 self.data_mut().str_files.insert(path.clone(), file_str);
292 }293 }
293 Ok(self.data().str_files.get(&path).cloned().unwrap())294 Ok(self.data().str_files.get(&path).cloned().unwrap())
294 }295 }
296 pub(crate) fn import_file_bin(&self, from: &Path, path: &Path) -> Result<Rc<[u8]>> {
297 let path = self.resolve_file(from, path)?;
298 if !self.data().bin_files.contains_key(&path) {
299 let file_bin = self.load_file_bin(&path)?;
300 self.data_mut().bin_files.insert(path.clone(), file_bin);
301 }
302 Ok(self.data().bin_files.get(&path).cloned().unwrap())
303 }
295304
296 fn evaluate_loaded_file_raw(&self, name: &Path) -> Result<Val> {305 fn evaluate_loaded_file_raw(&self, name: &Path) -> Result<Val> {
297 let expr: LocExpr = {306 let expr: LocExpr = {
607 pub fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {616 pub fn resolve_file(&self, from: &Path, path: &Path) -> Result<Rc<Path>> {
608 self.settings().import_resolver.resolve_file(from, path)617 self.settings().import_resolver.resolve_file(from, path)
609 }618 }
610 pub fn load_file_contents(&self, path: &Path) -> Result<IStr> {619 pub fn load_file_str(&self, path: &Path) -> Result<IStr> {
611 self.settings().import_resolver.load_file_contents(path)620 self.settings().import_resolver.load_file_str(path)
612 }621 }
622 pub fn load_file_bin(&self, path: &Path) -> Result<Rc<[u8]>> {
623 self.settings().import_resolver.load_file_bin(path)
624 }
613625
614 pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {626 pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {
615 Ref::map(self.settings(), |s| &*s.import_resolver)627 Ref::map(self.settings(), |s| &*s.import_resolver)
687 primitive_equals, EvaluationState,699 primitive_equals, EvaluationState,
688 };700 };
689 use gcmodule::{Cc, Trace};701 use gcmodule::{Cc, Trace};
690 use jrsonnet_interner::IStr;
691 use jrsonnet_parser::*;702 use jrsonnet_parser::*;
692 use std::{703 use std::{
693 path::{Path, PathBuf},704 path::{Path, PathBuf},
1204 Ok(())1215 Ok(())
1205 }1216 }
12061217
1207 struct TestImportResolver(IStr);1218 struct TestImportResolver(Vec<u8>);
1208 impl crate::import::ImportResolver for TestImportResolver {1219 impl crate::import::ImportResolver for TestImportResolver {
1209 fn resolve_file(&self, _: &Path, _: &Path) -> crate::error::Result<Rc<Path>> {1220 fn resolve_file(&self, _: &Path, _: &Path) -> crate::error::Result<Rc<Path>> {
1210 Ok(PathBuf::from("/test").into())1221 Ok(PathBuf::from("/test").into())
1211 }1222 }
12121223
1213 fn load_file_contents(&self, _: &Path) -> crate::error::Result<IStr> {1224 fn load_file_contents(&self, _: &Path) -> crate::error::Result<Vec<u8>> {
1214 Ok(self.0.clone())1225 Ok(self.0.clone())
1215 }1226 }
12161227
1217 unsafe fn as_any(&self) -> &dyn std::any::Any {1228 unsafe fn as_any(&self) -> &dyn std::any::Any {
1218 panic!()1229 panic!()
1219 }1230 }
1231
1232 fn load_file_bin(&self, _resolved: &Path) -> crate::error::Result<Rc<[u8]>> {
1233 panic!()
1234 }
1220 }1235 }
12211236
1222 #[test]1237 #[test]
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
1use std::convert::{TryFrom, TryInto};1use std::{
2 convert::{TryFrom, TryInto},
3 rc::Rc,
4};
25
3use gcmodule::Cc;6use gcmodule::Cc;
4use jrsonnet_interner::IStr;7use jrsonnet_interner::IStr;
306 }309 }
307}310}
311
312/// Specialization
313pub struct Bytes(pub Rc<[u8]>);
314
315impl Typed for Bytes {
316 const TYPE: &'static ComplexValType =
317 &ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));
318}
319impl TryFrom<Val> for Bytes {
320 type Error = LocError;
321
322 fn try_from(value: Val) -> Result<Self> {
323 match value {
324 Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),
325 _ => {
326 <Self as Typed>::TYPE.check(&value)?;
327 match value {
328 Val::Arr(a) => {
329 let mut out = Vec::with_capacity(a.len());
330 for e in a.iter() {
331 let r = e?;
332 out.push(u8::try_from(r)?);
333 }
334 Ok(Self(out.into()))
335 }
336 _ => unreachable!(),
337 }
338 }
339 }
340 }
341}
342impl TryFrom<Bytes> for Val {
343 type Error = LocError;
344
345 fn try_from(value: Bytes) -> Result<Self> {
346 Ok(Val::Arr(ArrValue::Bytes(value.0)))
347 }
348}
308349
309pub struct M1;350pub struct M1;
310impl Typed for M1 {351impl Typed for M1 {
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
174#[derive(Debug, Clone, Trace)]174#[derive(Debug, Clone, Trace)]
175#[force_tracking]175#[force_tracking]
176pub enum ArrValue {176pub enum ArrValue {
177 Bytes(#[skip_trace] Rc<[u8]>),
177 Lazy(Cc<Vec<LazyVal>>),178 Lazy(Cc<Vec<LazyVal>>),
178 Eager(Cc<Vec<Val>>),179 Eager(Cc<Vec<Val>>),
179 Extended(Box<(Self, Self)>),180 Extended(Box<(Self, Self)>),
185186
186 pub fn len(&self) -> usize {187 pub fn len(&self) -> usize {
187 match self {188 match self {
189 Self::Bytes(i) => i.len(),
188 Self::Lazy(l) => l.len(),190 Self::Lazy(l) => l.len(),
189 Self::Eager(e) => e.len(),191 Self::Eager(e) => e.len(),
190 Self::Extended(v) => v.0.len() + v.1.len(),192 Self::Extended(v) => v.0.len() + v.1.len(),
197199
198 pub fn get(&self, index: usize) -> Result<Option<Val>> {200 pub fn get(&self, index: usize) -> Result<Option<Val>> {
199 match self {201 match self {
202 Self::Bytes(i) => i
203 .get(index)
204 .map_or(Ok(None), |v| Ok(Some(Val::Num(*v as f64)))),
200 Self::Lazy(vec) => {205 Self::Lazy(vec) => {
201 if let Some(v) = vec.get(index) {206 if let Some(v) = vec.get(index) {
202 Ok(Some(v.evaluate()?))207 Ok(Some(v.evaluate()?))
218223
219 pub fn get_lazy(&self, index: usize) -> Option<LazyVal> {224 pub fn get_lazy(&self, index: usize) -> Option<LazyVal> {
220 match self {225 match self {
226 Self::Bytes(i) => i
227 .get(index)
228 .map(|b| LazyVal::new_resolved(Val::Num(*b as f64))),
221 Self::Lazy(vec) => vec.get(index).cloned(),229 Self::Lazy(vec) => vec.get(index).cloned(),
222 Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),230 Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),
223 Self::Extended(v) => {231 Self::Extended(v) => {
233241
234 pub fn evaluated(&self) -> Result<Cc<Vec<Val>>> {242 pub fn evaluated(&self) -> Result<Cc<Vec<Val>>> {
235 Ok(match self {243 Ok(match self {
244 Self::Bytes(i) => {
245 let mut out = Vec::with_capacity(i.len());
246 for v in i.iter() {
247 out.push(Val::Num(*v as f64));
248 }
249 Cc::new(out)
250 }
236 Self::Lazy(vec) => {251 Self::Lazy(vec) => {
237 let mut out = Vec::with_capacity(vec.len());252 let mut out = Vec::with_capacity(vec.len());
238 for item in vec.iter() {253 for item in vec.iter() {
253268
254 pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {269 pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {
255 (0..self.len()).map(move |idx| match self {270 (0..self.len()).map(move |idx| match self {
271 Self::Bytes(b) => Ok(Val::Num(b[idx] as f64)),
256 Self::Lazy(l) => l[idx].evaluate(),272 Self::Lazy(l) => l[idx].evaluate(),
257 Self::Eager(e) => Ok(e[idx].clone()),273 Self::Eager(e) => Ok(e[idx].clone()),
258 Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),274 Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),
261277
262 pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {278 pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {
263 (0..self.len()).map(move |idx| match self {279 (0..self.len()).map(move |idx| match self {
280 Self::Bytes(b) => LazyVal::new_resolved(Val::Num(b[idx] as f64)),
264 Self::Lazy(l) => l[idx].clone(),281 Self::Lazy(l) => l[idx].clone(),
265 Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),282 Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),
266 Self::Extended(_) => self.get_lazy(idx).unwrap(),283 Self::Extended(_) => self.get_lazy(idx).unwrap(),
269286
270 pub fn reversed(self) -> Self {287 pub fn reversed(self) -> Self {
271 match self {288 match self {
289 Self::Bytes(b) => {
290 let mut out = b.to_vec();
291 out.reverse();
292 Self::Bytes(out.into())
293 }
272 Self::Lazy(vec) => {294 Self::Lazy(vec) => {
273 let mut out = (&vec as &Vec<_>).clone();295 let mut out = (&vec as &Vec<_>).clone();
274 out.reverse();296 out.reverse();
modifiedcrates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth
4use std::{4use std::{
5 borrow::Cow,5 borrow::Cow,
6 cell::RefCell,6 cell::RefCell,
7 convert::TryFrom,
7 fmt::{self, Display},8 fmt::{self, Display},
8 hash::{BuildHasherDefault, Hash, Hasher},9 hash::{BuildHasherDefault, Hash, Hasher},
9 ops::Deref,10 ops::Deref,
10 rc::Rc,11 rc::Rc,
12 str::Utf8Error,
11};13};
1214
13#[derive(Clone, PartialOrd, Ord, Eq)]15#[derive(Clone, PartialOrd, Ord, Eq)]
85 }87 }
86}88}
89
90impl TryFrom<&[u8]> for IStr {
91 type Error = Utf8Error;
92
93 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
94 let str = std::str::from_utf8(value)?;
95 Ok(str.into())
96 }
97}
8798
88impl From<String> for IStr {99impl From<String> for IStr {
89 fn from(str: String) -> Self {100 fn from(str: String) -> Self {
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
285 Import(PathBuf),285 Import(PathBuf),
286 /// importStr "file.txt"286 /// importStr "file.txt"
287 ImportStr(PathBuf),287 ImportStr(PathBuf),
288 /// importBin "file.txt"
289 ImportBin(PathBuf),
288 /// error "I'm broken"290 /// error "I'm broken"
289 ErrorStmt(LocExpr),291 ErrorStmt(LocExpr),
290 /// a(b, c)292 /// a(b, c)
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
53 rule number() -> f64 = quiet!{a:$(uint_str() ("." uint_str())? (['e'|'E'] (s:['+'|'-'])? uint_str())?) {? a.parse().map_err(|_| "<number>") }} / expected!("<number>")53 rule number() -> f64 = quiet!{a:$(uint_str() ("." uint_str())? (['e'|'E'] (s:['+'|'-'])? uint_str())?) {? a.parse().map_err(|_| "<number>") }} / expected!("<number>")
5454
55 /// Reserved word followed by any non-alphanumberic55 /// Reserved word followed by any non-alphanumberic
56 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()56 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "importbin" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()
57 rule id() = quiet!{ !reserved() alpha() (alpha() / digit())*} / expected!("<identifier>")57 rule id() = quiet!{ !reserved() alpha() (alpha() / digit())*} / expected!("<identifier>")
5858
59 rule keyword(id: &'static str) -> ()59 rule keyword(id: &'static str) -> ()
218 / array_comp_expr(s)218 / array_comp_expr(s)
219219
220 / keyword("importstr") _ path:string() {Expr::ImportStr(PathBuf::from(path))}220 / keyword("importstr") _ path:string() {Expr::ImportStr(PathBuf::from(path))}
221 / keyword("importbin") _ path:string() {Expr::ImportBin(PathBuf::from(path))}
221 / keyword("import") _ path:string() {Expr::Import(PathBuf::from(path))}222 / keyword("import") _ path:string() {Expr::Import(PathBuf::from(path))}
222223
223 / var_expr(s)224 / var_expr(s)