difftreelog
perf lazy slice
in: master
5 files changed
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -43,33 +43,45 @@
pub fn std_slice(
indexable: IndexableVal,
- index: Option<usize>,
- end: Option<usize>,
- step: Option<usize>,
+ index: Option<BoundedUsize<0, { i32::MAX as usize }>>,
+ end: Option<BoundedUsize<0, { i32::MAX as usize }>>,
+ step: Option<BoundedUsize<1, { i32::MAX as usize }>>,
) -> Result<Val> {
- let index = index.unwrap_or(0);
- let end = end.unwrap_or_else(|| match &indexable {
- IndexableVal::Str(_) => usize::MAX,
- IndexableVal::Arr(v) => v.len(),
- });
- let step = step.unwrap_or(1);
match &indexable {
- IndexableVal::Str(s) => Ok(Val::Str(
+ IndexableVal::Str(s) => {
+ let index = index.as_deref().copied().unwrap_or(0);
+ let end = end.as_deref().copied().unwrap_or(usize::MAX);
+ let step = step.as_deref().copied().unwrap_or(1);
+
+ if index >= end {
+ return Ok(Val::Str("".into()));
+ }
+
+ Ok(Val::Str(
(s.chars()
.skip(index)
.take(end - index)
.step_by(step)
.collect::<String>())
.into(),
- )),
- IndexableVal::Arr(arr) => Ok(Val::Arr(
- (arr.iter()
- .skip(index)
- .take(end - index)
- .step_by(step)
- .collect::<Result<Vec<Val>>>()?)
- .into(),
- )),
+ ))
+ }
+ IndexableVal::Arr(arr) => {
+ let index = index.as_deref().copied().unwrap_or(0);
+ let end = end.as_deref().copied().unwrap_or(usize::MAX).min(arr.len());
+ let step = step.as_deref().copied().unwrap_or(1);
+
+ if index >= end {
+ return Ok(Val::Arr(ArrValue::new_eager()));
+ }
+
+ Ok(Val::Arr(ArrValue::Slice(Box::new(Slice {
+ inner: arr.clone(),
+ from: index as u32,
+ to: end as u32,
+ step: step as u32,
+ }))))
+ }
}
}
@@ -221,9 +233,9 @@
#[jrsonnet_macros::builtin]
fn builtin_slice(
indexable: IndexableVal,
- index: Option<usize>,
- end: Option<usize>,
- step: Option<usize>,
+ index: Option<BoundedUsize<0, { i32::MAX as usize }>>,
+ end: Option<BoundedUsize<0, { i32::MAX as usize }>>,
+ step: Option<BoundedUsize<1, { i32::MAX as usize }>>,
) -> Result<Any> {
std_slice(indexable, index, end, step).map(Any)
}
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -191,3 +191,10 @@
return Err($e.into())
};
}
+
+#[macro_export]
+macro_rules! throw_runtime {
+ ($($tt:tt)*) => {
+ return Err($crate::error::Error::RuntimeError(format!($($tt)*).into()).into())
+ };
+}
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -665,23 +665,28 @@
}
Slice(value, desc) => {
let indexable = evaluate(context.clone(), value)?;
+ let loc = CallLocation::new(loc);
- fn parse_num(
+ fn parse_idx<const MIN: usize>(
+ loc: CallLocation,
context: &Context,
- expr: Option<&LocExpr>,
+ expr: &Option<LocExpr>,
desc: &'static str,
- ) -> Result<Option<usize>> {
- Ok(match expr {
- Some(s) => evaluate(context.clone(), s)?
- .try_cast_nullable_num(desc)?
- .map(|v| v as usize),
- None => None,
- })
+ ) -> Result<Option<BoundedUsize<MIN, { i32::MAX as usize }>>> {
+ if let Some(value) = expr {
+ Ok(Some(push_frame(
+ loc,
+ || format!("slice {}", desc),
+ || Ok(evaluate(context.clone(), value)?.try_into()?),
+ )?))
+ } else {
+ Ok(None)
+ }
}
- let start = parse_num(&context, desc.start.as_ref(), "start")?;
- let end = parse_num(&context, desc.end.as_ref(), "end")?;
- let step = parse_num(&context, desc.step.as_ref(), "step")?;
+ let start = parse_idx(loc, &context, &desc.start, "start")?;
+ let end = parse_idx(loc, &context, &desc.end, "end")?;
+ let step = parse_idx(loc, &context, &desc.step, "step")?;
std_slice(indexable.into_indexable()?, start, end, step)?
}
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth1use std::{2 convert::{TryFrom, TryInto},3 rc::Rc,4};56use gcmodule::Cc;7use jrsonnet_interner::IStr;8pub use jrsonnet_macros::Typed;9use jrsonnet_types::{ComplexValType, ValType};1011use crate::{12 error::{Error::*, LocError, Result},13 throw,14 typed::CheckType,15 ArrValue, FuncDesc, FuncVal, IndexableVal, ObjValue, ObjValueBuilder, Val,16};1718pub trait TypedObj: Typed {19 fn serialize(self, out: &mut ObjValueBuilder) -> Result<()>;20 fn parse(obj: &ObjValue) -> Result<Self>;21 fn into_object(self) -> Result<ObjValue> {22 let mut builder = ObjValueBuilder::new();23 self.serialize(&mut builder)?;24 Ok(builder.build())25 }26}2728pub trait Typed: TryFrom<Val, Error = LocError> + TryInto<Val, Error = LocError> {29 const TYPE: &'static ComplexValType;30}3132macro_rules! impl_int {33 ($($ty:ty)*) => {$(34 impl Typed for $ty {35 const TYPE: &'static ComplexValType =36 &ComplexValType::BoundedNumber(Some(Self::MIN as f64), Some(Self::MAX as f64));37 }38 impl TryFrom<Val> for $ty {39 type Error = LocError;4041 fn try_from(value: Val) -> Result<Self> {42 <Self as Typed>::TYPE.check(&value)?;43 match value {44 Val::Num(n) => {45 if n.trunc() != n {46 throw!(RuntimeError(47 format!(48 "cannot convert number with fractional part to {}",49 stringify!($ty)50 )51 .into()52 ))53 }54 Ok(n as Self)55 }56 _ => unreachable!(),57 }58 }59 }60 impl TryFrom<$ty> for Val {61 type Error = LocError;6263 fn try_from(value: $ty) -> Result<Self> {64 Ok(Self::Num(value as f64))65 }66 }67 )*};68}6970impl_int!(i8 u8 i16 u16 i32 u32);7172impl Typed for f64 {73 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Num);74}75impl TryFrom<Val> for f64 {76 type Error = LocError;7778 fn try_from(value: Val) -> Result<Self> {79 <Self as Typed>::TYPE.check(&value)?;80 match value {81 Val::Num(n) => Ok(n),82 _ => unreachable!(),83 }84 }85}86impl TryFrom<f64> for Val {87 type Error = LocError;8889 fn try_from(value: f64) -> Result<Self> {90 Ok(Self::Num(value))91 }92}9394pub struct PositiveF64(pub f64);95impl Typed for PositiveF64 {96 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(0.0), None);97}98impl TryFrom<Val> for PositiveF64 {99 type Error = LocError;100101 fn try_from(value: Val) -> Result<Self> {102 <Self as Typed>::TYPE.check(&value)?;103 match value {104 Val::Num(n) => Ok(Self(n)),105 _ => unreachable!(),106 }107 }108}109impl TryFrom<PositiveF64> for Val {110 type Error = LocError;111112 fn try_from(value: PositiveF64) -> Result<Self> {113 Ok(Self::Num(value.0))114 }115}116117impl Typed for usize {118 // It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility119 const TYPE: &'static ComplexValType =120 &ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));121}122impl TryFrom<Val> for usize {123 type Error = LocError;124125 fn try_from(value: Val) -> Result<Self> {126 <Self as Typed>::TYPE.check(&value)?;127 match value {128 Val::Num(n) => {129 if n.trunc() != n {130 throw!(RuntimeError(131 "cannot convert number with fractional part to usize".into()132 ))133 }134 Ok(n as Self)135 }136 _ => unreachable!(),137 }138 }139}140impl TryFrom<usize> for Val {141 type Error = LocError;142143 fn try_from(value: usize) -> Result<Self> {144 if value > u32::MAX as usize {145 throw!(RuntimeError("number is too large".into()))146 }147 Ok(Self::Num(value as f64))148 }149}150151impl Typed for IStr {152 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);153}154impl TryFrom<Val> for IStr {155 type Error = LocError;156157 fn try_from(value: Val) -> Result<Self> {158 <Self as Typed>::TYPE.check(&value)?;159 match value {160 Val::Str(s) => Ok(s),161 _ => unreachable!(),162 }163 }164}165impl TryFrom<IStr> for Val {166 type Error = LocError;167168 fn try_from(value: IStr) -> Result<Self> {169 Ok(Self::Str(value))170 }171}172173impl Typed for String {174 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);175}176impl TryFrom<Val> for String {177 type Error = LocError;178179 fn try_from(value: Val) -> Result<Self> {180 <Self as Typed>::TYPE.check(&value)?;181 match value {182 Val::Str(s) => Ok(s.to_string()),183 _ => unreachable!(),184 }185 }186}187impl TryFrom<String> for Val {188 type Error = LocError;189190 fn try_from(value: String) -> Result<Self> {191 Ok(Self::Str(value.into()))192 }193}194195impl Typed for char {196 const TYPE: &'static ComplexValType = &ComplexValType::Char;197}198impl TryFrom<Val> for char {199 type Error = LocError;200201 fn try_from(value: Val) -> Result<Self> {202 <Self as Typed>::TYPE.check(&value)?;203 match value {204 Val::Str(s) => Ok(s.chars().next().unwrap()),205 _ => unreachable!(),206 }207 }208}209impl TryFrom<char> for Val {210 type Error = LocError;211212 fn try_from(value: char) -> Result<Self> {213 Ok(Self::Str(value.to_string().into()))214 }215}216217impl<T> Typed for Vec<T>218where219 T: Typed,220 T: TryFrom<Val, Error = LocError>,221 T: TryInto<Val, Error = LocError>,222{223 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);224}225impl<T> TryFrom<Val> for Vec<T>226where227 T: Typed,228 T: TryFrom<Val, Error = LocError>,229 T: TryInto<Val, Error = LocError>,230{231 type Error = LocError;232233 fn try_from(value: Val) -> Result<Self> {234 <Self as Typed>::TYPE.check(&value)?;235 match value {236 Val::Arr(a) => {237 let mut o = Self::with_capacity(a.len());238 for i in a.iter() {239 o.push(T::try_from(i?)?);240 }241 Ok(o)242 }243 _ => unreachable!(),244 }245 }246}247impl<T> TryFrom<Vec<T>> for Val248where249 T: Typed,250 T: TryFrom<Self, Error = LocError>,251 T: TryInto<Self, Error = LocError>,252{253 type Error = LocError;254255 fn try_from(value: Vec<T>) -> Result<Self> {256 let mut o = Vec::with_capacity(value.len());257 for i in value {258 o.push(i.try_into()?);259 }260 Ok(Self::Arr(o.into()))261 }262}263264/// To be used in Vec<Any>265/// Regular Val can't be used here, because it has wrong TryFrom::Error type266#[derive(Clone)]267pub struct Any(pub Val);268269impl Typed for Any {270 const TYPE: &'static ComplexValType = &ComplexValType::Any;271}272impl TryFrom<Val> for Any {273 type Error = LocError;274275 fn try_from(value: Val) -> Result<Self> {276 Ok(Self(value))277 }278}279impl TryFrom<Any> for Val {280 type Error = LocError;281282 fn try_from(value: Any) -> Result<Self> {283 Ok(value.0)284 }285}286287/// Specialization, provides faster TryFrom<VecVal> for Val288pub struct VecVal(pub Cc<Vec<Val>>);289290impl Typed for VecVal {291 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);292}293impl TryFrom<Val> for VecVal {294 type Error = LocError;295296 fn try_from(value: Val) -> Result<Self> {297 <Self as Typed>::TYPE.check(&value)?;298 match value {299 Val::Arr(a) => Ok(Self(a.evaluated()?)),300 _ => unreachable!(),301 }302 }303}304impl TryFrom<VecVal> for Val {305 type Error = LocError;306307 fn try_from(value: VecVal) -> Result<Self> {308 Ok(Self::Arr(ArrValue::Eager(value.0)))309 }310}311312/// Specialization313pub struct Bytes(pub Rc<[u8]>);314315impl 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;321322 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;344345 fn try_from(value: Bytes) -> Result<Self> {346 Ok(Self::Arr(ArrValue::Bytes(value.0)))347 }348}349350pub struct M1;351impl Typed for M1 {352 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));353}354impl TryFrom<Val> for M1 {355 type Error = LocError;356357 fn try_from(value: Val) -> Result<Self> {358 <Self as Typed>::TYPE.check(&value)?;359 Ok(Self)360 }361}362impl TryFrom<M1> for Val {363 type Error = LocError;364365 fn try_from(_: M1) -> Result<Self> {366 Ok(Self::Num(-1.0))367 }368}369370macro_rules! decl_either {371 ($($name: ident, $($id: ident)*);*) => {$(372 pub enum $name<$($id),*> {373 $($id($id)),*374 }375 impl<$($id),*> Typed for $name<$($id),*>376 where377 $($id: Typed,)*378 {379 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);380 }381 impl<$($id),*> TryFrom<Val> for $name<$($id),*>382 where383 $($id: Typed,)*384 {385 type Error = LocError;386387 fn try_from(value: Val) -> Result<Self> {388 $(389 if $id::TYPE.check(&value).is_ok() {390 $id::try_from(value).map(Self::$id)391 } else392 )* {393 <Self as Typed>::TYPE.check(&value)?;394 unreachable!()395 }396 }397 }398 impl<$($id),*> TryFrom<$name<$($id),*>> for Val399 where400 $($id: Typed,)*401 {402 type Error = LocError;403 fn try_from(value: $name<$($id),*>) -> Result<Self> {404 match value {$(405 $name::$id(v) => v.try_into()406 ),*}407 }408 }409 )*}410}411decl_either!(412 Either1, A;413 Either2, A B;414 Either3, A B C;415 Either4, A B C D;416 Either5, A B C D E;417 Either6, A B C D E F;418 Either7, A B C D E F G419);420#[macro_export]421macro_rules! Either {422 ($a:ty) => {Either1<$a>};423 ($a:ty, $b:ty) => {Either2<$a, $b>};424 ($a:ty, $b:ty, $c:ty) => {Either3<$a, $b, $c>};425 ($a:ty, $b:ty, $c:ty, $d:ty) => {Either4<$a, $b, $c, $d>};426 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty) => {Either5<$a, $b, $c, $d, $e>};427 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty) => {Either6<$a, $b, $c, $d, $e, $f>};428 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty) => {Either7<$a, $b, $c, $d, $e, $f, $g>};429}430431pub type MyType = Either![u32, f64, String];432433impl Typed for ArrValue {434 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);435}436impl TryFrom<Val> for ArrValue {437 type Error = LocError;438439 fn try_from(value: Val) -> Result<Self> {440 <Self as Typed>::TYPE.check(&value)?;441 match value {442 Val::Arr(a) => Ok(a),443 _ => unreachable!(),444 }445 }446}447impl TryFrom<ArrValue> for Val {448 type Error = LocError;449450 fn try_from(value: ArrValue) -> Result<Self> {451 Ok(Self::Arr(value))452 }453}454455impl Typed for FuncVal {456 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);457}458impl TryFrom<Val> for FuncVal {459 type Error = LocError;460461 fn try_from(value: Val) -> Result<Self> {462 <Self as Typed>::TYPE.check(&value)?;463 match value {464 Val::Func(a) => Ok(a),465 _ => unreachable!(),466 }467 }468}469impl TryFrom<FuncVal> for Val {470 type Error = LocError;471472 fn try_from(value: FuncVal) -> Result<Self> {473 Ok(Self::Func(value))474 }475}476477impl Typed for Cc<FuncDesc> {478 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);479}480impl TryFrom<Val> for Cc<FuncDesc> {481 type Error = LocError;482483 fn try_from(value: Val) -> Result<Self, Self::Error> {484 <Self as Typed>::TYPE.check(&value)?;485 match value {486 Val::Func(FuncVal::Normal(desc)) => Ok(desc),487 Val::Func(_) => throw!(RuntimeError("expected normal function, not builtin".into())),488 _ => unreachable!(),489 }490 }491}492impl TryFrom<Cc<FuncDesc>> for Val {493 type Error = LocError;494495 fn try_from(value: Cc<FuncDesc>) -> Result<Self, Self::Error> {496 Ok(Self::Func(FuncVal::Normal(value)))497 }498}499500impl Typed for ObjValue {501 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Obj);502}503impl TryFrom<Val> for ObjValue {504 type Error = LocError;505506 fn try_from(value: Val) -> Result<Self> {507 <Self as Typed>::TYPE.check(&value)?;508 match value {509 Val::Obj(a) => Ok(a),510 _ => unreachable!(),511 }512 }513}514impl TryFrom<ObjValue> for Val {515 type Error = LocError;516517 fn try_from(value: ObjValue) -> Result<Self> {518 Ok(Self::Obj(value))519 }520}521522impl Typed for bool {523 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Bool);524}525impl TryFrom<Val> for bool {526 type Error = LocError;527528 fn try_from(value: Val) -> Result<Self> {529 <Self as Typed>::TYPE.check(&value)?;530 match value {531 Val::Bool(a) => Ok(a),532 _ => unreachable!(),533 }534 }535}536impl TryFrom<bool> for Val {537 type Error = LocError;538539 fn try_from(value: bool) -> Result<Self> {540 Ok(Self::Bool(value))541 }542}543544impl Typed for IndexableVal {545 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[546 &ComplexValType::Simple(ValType::Arr),547 &ComplexValType::Simple(ValType::Str),548 ]);549}550impl TryFrom<Val> for IndexableVal {551 type Error = LocError;552553 fn try_from(value: Val) -> Result<Self> {554 <Self as Typed>::TYPE.check(&value)?;555 value.into_indexable()556 }557}558impl TryFrom<IndexableVal> for Val {559 type Error = LocError;560561 fn try_from(value: IndexableVal) -> Result<Self> {562 match value {563 IndexableVal::Str(s) => Ok(Self::Str(s)),564 IndexableVal::Arr(a) => Ok(Self::Arr(a)),565 }566 }567}568569pub struct Null;570impl Typed for Null {571 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Null);572}573impl TryFrom<Val> for Null {574 type Error = LocError;575576 fn try_from(value: Val) -> Result<Self> {577 <Self as Typed>::TYPE.check(&value)?;578 Ok(Self)579 }580}581impl TryFrom<Null> for Val {582 type Error = LocError;583584 fn try_from(_: Null) -> Result<Self> {585 Ok(Self::Null)586 }587}1use std::{2 convert::{TryFrom, TryInto},3 ops::Deref,4 rc::Rc,5};67use gcmodule::Cc;8use jrsonnet_interner::IStr;9pub use jrsonnet_macros::Typed;10use jrsonnet_types::{ComplexValType, ValType};1112use crate::{13 error::{Error::*, LocError, Result},14 throw,15 typed::CheckType,16 val::{ArrValue, FuncDesc, FuncVal, IndexableVal},17 ObjValue, ObjValueBuilder, Val,18};1920pub trait TypedObj: Typed {21 fn serialize(self, out: &mut ObjValueBuilder) -> Result<()>;22 fn parse(obj: &ObjValue) -> Result<Self>;23 fn into_object(self) -> Result<ObjValue> {24 let mut builder = ObjValueBuilder::new();25 self.serialize(&mut builder)?;26 Ok(builder.build())27 }28}2930pub trait Typed: TryFrom<Val, Error = LocError> + TryInto<Val, Error = LocError> {31 const TYPE: &'static ComplexValType;32}3334macro_rules! impl_int {35 ($($ty:ty)*) => {$(36 impl Typed for $ty {37 const TYPE: &'static ComplexValType =38 &ComplexValType::BoundedNumber(Some(Self::MIN as f64), Some(Self::MAX as f64));39 }40 impl TryFrom<Val> for $ty {41 type Error = LocError;4243 fn try_from(value: Val) -> Result<Self> {44 <Self as Typed>::TYPE.check(&value)?;45 match value {46 Val::Num(n) => {47 if n.trunc() != n {48 throw!(RuntimeError(49 format!(50 "cannot convert number with fractional part to {}",51 stringify!($ty)52 )53 .into()54 ))55 }56 Ok(n as Self)57 }58 _ => unreachable!(),59 }60 }61 }62 impl TryFrom<$ty> for Val {63 type Error = LocError;6465 fn try_from(value: $ty) -> Result<Self> {66 Ok(Self::Num(value as f64))67 }68 }69 )*};70}7172impl_int!(i8 u8 i16 u16 i32 u32);7374macro_rules! impl_bounded_int {75 ($($name:ident = $ty:ty)*) => {$(76 #[derive(Clone, Copy)]77 pub struct $name<const MIN: $ty, const MAX: $ty>($ty);78 impl<const MIN: $ty, const MAX: $ty> $name<MIN, MAX> {79 pub const fn new(value: $ty) -> Option<$name<MIN, MAX>> {80 if value >= MIN && value <= MAX {81 Some(Self(value))82 } else {83 None84 }85 }86 pub const fn value(self) -> $ty {87 self.088 }89 }90 impl<const MIN: $ty, const MAX: $ty> Deref for $name<MIN, MAX> {91 type Target = $ty;92 fn deref(&self) -> &Self::Target {93 &self.094 }95 }9697 impl<const MIN: $ty, const MAX: $ty> Typed for $name<MIN, MAX> {98 const TYPE: &'static ComplexValType =99 &ComplexValType::BoundedNumber(100 Some(MIN as f64),101 Some(MAX as f64),102 );103 }104 impl<const MIN: $ty, const MAX: $ty> TryFrom<Val> for $name<MIN, MAX> {105 type Error = LocError;106107 fn try_from(value: Val) -> Result<Self> {108 <Self as Typed>::TYPE.check(&value)?;109 match value {110 Val::Num(n) => {111 if n.trunc() != n {112 throw!(RuntimeError(113 format!(114 "cannot convert number with fractional part to {}",115 stringify!($ty)116 )117 .into()118 ))119 }120 Ok(Self(n as $ty))121 }122 _ => unreachable!(),123 }124 }125 }126 impl<const MIN: $ty, const MAX: $ty> TryFrom<$name<MIN, MAX>> for Val {127 type Error = LocError;128129 fn try_from(value: $name<MIN, MAX>) -> Result<Self> {130 Ok(Self::Num(value.0 as f64))131 }132 }133 )*};134}135136impl_bounded_int!(137 BoundedI8 = i8138 BoundedI16 = i16139 BoundedI32 = i32140 BoundedI64 = i64141 BoundedUsize = usize142);143144impl Typed for f64 {145 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Num);146}147impl TryFrom<Val> for f64 {148 type Error = LocError;149150 fn try_from(value: Val) -> Result<Self> {151 <Self as Typed>::TYPE.check(&value)?;152 match value {153 Val::Num(n) => Ok(n),154 _ => unreachable!(),155 }156 }157}158impl TryFrom<f64> for Val {159 type Error = LocError;160161 fn try_from(value: f64) -> Result<Self> {162 Ok(Self::Num(value))163 }164}165166pub struct PositiveF64(pub f64);167impl Typed for PositiveF64 {168 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(0.0), None);169}170impl TryFrom<Val> for PositiveF64 {171 type Error = LocError;172173 fn try_from(value: Val) -> Result<Self> {174 <Self as Typed>::TYPE.check(&value)?;175 match value {176 Val::Num(n) => Ok(Self(n)),177 _ => unreachable!(),178 }179 }180}181impl TryFrom<PositiveF64> for Val {182 type Error = LocError;183184 fn try_from(value: PositiveF64) -> Result<Self> {185 Ok(Self::Num(value.0))186 }187}188189impl Typed for usize {190 // It is possible to store 54 bits of precision in f64, but leaving u32::MAX here for compatibility191 const TYPE: &'static ComplexValType =192 &ComplexValType::BoundedNumber(Some(0.0), Some(4294967295.0));193}194impl TryFrom<Val> for usize {195 type Error = LocError;196197 fn try_from(value: Val) -> Result<Self> {198 <Self as Typed>::TYPE.check(&value)?;199 match value {200 Val::Num(n) => {201 if n.trunc() != n {202 throw!(RuntimeError(203 "cannot convert number with fractional part to usize".into()204 ))205 }206 Ok(n as Self)207 }208 _ => unreachable!(),209 }210 }211}212impl TryFrom<usize> for Val {213 type Error = LocError;214215 fn try_from(value: usize) -> Result<Self> {216 if value > u32::MAX as usize {217 throw!(RuntimeError("number is too large".into()))218 }219 Ok(Self::Num(value as f64))220 }221}222223impl Typed for IStr {224 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);225}226impl TryFrom<Val> for IStr {227 type Error = LocError;228229 fn try_from(value: Val) -> Result<Self> {230 <Self as Typed>::TYPE.check(&value)?;231 match value {232 Val::Str(s) => Ok(s),233 _ => unreachable!(),234 }235 }236}237impl TryFrom<IStr> for Val {238 type Error = LocError;239240 fn try_from(value: IStr) -> Result<Self> {241 Ok(Self::Str(value))242 }243}244245impl Typed for String {246 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Str);247}248impl TryFrom<Val> for String {249 type Error = LocError;250251 fn try_from(value: Val) -> Result<Self> {252 <Self as Typed>::TYPE.check(&value)?;253 match value {254 Val::Str(s) => Ok(s.to_string()),255 _ => unreachable!(),256 }257 }258}259impl TryFrom<String> for Val {260 type Error = LocError;261262 fn try_from(value: String) -> Result<Self> {263 Ok(Self::Str(value.into()))264 }265}266267impl Typed for char {268 const TYPE: &'static ComplexValType = &ComplexValType::Char;269}270impl TryFrom<Val> for char {271 type Error = LocError;272273 fn try_from(value: Val) -> Result<Self> {274 <Self as Typed>::TYPE.check(&value)?;275 match value {276 Val::Str(s) => Ok(s.chars().next().unwrap()),277 _ => unreachable!(),278 }279 }280}281impl TryFrom<char> for Val {282 type Error = LocError;283284 fn try_from(value: char) -> Result<Self> {285 Ok(Self::Str(value.to_string().into()))286 }287}288289impl<T> Typed for Vec<T>290where291 T: Typed,292 T: TryFrom<Val, Error = LocError>,293 T: TryInto<Val, Error = LocError>,294{295 const TYPE: &'static ComplexValType = &ComplexValType::ArrayRef(T::TYPE);296}297impl<T> TryFrom<Val> for Vec<T>298where299 T: Typed,300 T: TryFrom<Val, Error = LocError>,301 T: TryInto<Val, Error = LocError>,302{303 type Error = LocError;304305 fn try_from(value: Val) -> Result<Self> {306 <Self as Typed>::TYPE.check(&value)?;307 match value {308 Val::Arr(a) => {309 let mut o = Self::with_capacity(a.len());310 for i in a.iter() {311 o.push(T::try_from(i?)?);312 }313 Ok(o)314 }315 _ => unreachable!(),316 }317 }318}319impl<T> TryFrom<Vec<T>> for Val320where321 T: Typed,322 T: TryFrom<Self, Error = LocError>,323 T: TryInto<Self, Error = LocError>,324{325 type Error = LocError;326327 fn try_from(value: Vec<T>) -> Result<Self> {328 let mut o = Vec::with_capacity(value.len());329 for i in value {330 o.push(i.try_into()?);331 }332 Ok(Self::Arr(o.into()))333 }334}335336/// To be used in Vec<Any>337/// Regular Val can't be used here, because it has wrong TryFrom::Error type338#[derive(Clone)]339pub struct Any(pub Val);340341impl Typed for Any {342 const TYPE: &'static ComplexValType = &ComplexValType::Any;343}344impl TryFrom<Val> for Any {345 type Error = LocError;346347 fn try_from(value: Val) -> Result<Self> {348 Ok(Self(value))349 }350}351impl TryFrom<Any> for Val {352 type Error = LocError;353354 fn try_from(value: Any) -> Result<Self> {355 Ok(value.0)356 }357}358359/// Specialization, provides faster TryFrom<VecVal> for Val360pub struct VecVal(pub Cc<Vec<Val>>);361362impl Typed for VecVal {363 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);364}365impl TryFrom<Val> for VecVal {366 type Error = LocError;367368 fn try_from(value: Val) -> Result<Self> {369 <Self as Typed>::TYPE.check(&value)?;370 match value {371 Val::Arr(a) => Ok(Self(a.evaluated()?)),372 _ => unreachable!(),373 }374 }375}376impl TryFrom<VecVal> for Val {377 type Error = LocError;378379 fn try_from(value: VecVal) -> Result<Self> {380 Ok(Self::Arr(ArrValue::Eager(value.0)))381 }382}383384/// Specialization385pub struct Bytes(pub Rc<[u8]>);386387impl Typed for Bytes {388 const TYPE: &'static ComplexValType =389 &ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));390}391impl TryFrom<Val> for Bytes {392 type Error = LocError;393394 fn try_from(value: Val) -> Result<Self> {395 match value {396 Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),397 _ => {398 <Self as Typed>::TYPE.check(&value)?;399 match value {400 Val::Arr(a) => {401 let mut out = Vec::with_capacity(a.len());402 for e in a.iter() {403 let r = e?;404 out.push(u8::try_from(r)?);405 }406 Ok(Self(out.into()))407 }408 _ => unreachable!(),409 }410 }411 }412 }413}414impl TryFrom<Bytes> for Val {415 type Error = LocError;416417 fn try_from(value: Bytes) -> Result<Self> {418 Ok(Self::Arr(ArrValue::Bytes(value.0)))419 }420}421422pub struct M1;423impl Typed for M1 {424 const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));425}426impl TryFrom<Val> for M1 {427 type Error = LocError;428429 fn try_from(value: Val) -> Result<Self> {430 <Self as Typed>::TYPE.check(&value)?;431 Ok(Self)432 }433}434impl TryFrom<M1> for Val {435 type Error = LocError;436437 fn try_from(_: M1) -> Result<Self> {438 Ok(Self::Num(-1.0))439 }440}441442macro_rules! decl_either {443 ($($name: ident, $($id: ident)*);*) => {$(444 pub enum $name<$($id),*> {445 $($id($id)),*446 }447 impl<$($id),*> Typed for $name<$($id),*>448 where449 $($id: Typed,)*450 {451 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[$($id::TYPE),*]);452 }453 impl<$($id),*> TryFrom<Val> for $name<$($id),*>454 where455 $($id: Typed,)*456 {457 type Error = LocError;458459 fn try_from(value: Val) -> Result<Self> {460 $(461 if $id::TYPE.check(&value).is_ok() {462 $id::try_from(value).map(Self::$id)463 } else464 )* {465 <Self as Typed>::TYPE.check(&value)?;466 unreachable!()467 }468 }469 }470 impl<$($id),*> TryFrom<$name<$($id),*>> for Val471 where472 $($id: Typed,)*473 {474 type Error = LocError;475 fn try_from(value: $name<$($id),*>) -> Result<Self> {476 match value {$(477 $name::$id(v) => v.try_into()478 ),*}479 }480 }481 )*}482}483decl_either!(484 Either1, A;485 Either2, A B;486 Either3, A B C;487 Either4, A B C D;488 Either5, A B C D E;489 Either6, A B C D E F;490 Either7, A B C D E F G491);492#[macro_export]493macro_rules! Either {494 ($a:ty) => {Either1<$a>};495 ($a:ty, $b:ty) => {Either2<$a, $b>};496 ($a:ty, $b:ty, $c:ty) => {Either3<$a, $b, $c>};497 ($a:ty, $b:ty, $c:ty, $d:ty) => {Either4<$a, $b, $c, $d>};498 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty) => {Either5<$a, $b, $c, $d, $e>};499 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty) => {Either6<$a, $b, $c, $d, $e, $f>};500 ($a:ty, $b:ty, $c:ty, $d:ty, $e:ty, $f:ty, $g:ty) => {Either7<$a, $b, $c, $d, $e, $f, $g>};501}502503pub type MyType = Either![u32, f64, String];504505impl Typed for ArrValue {506 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Arr);507}508impl TryFrom<Val> for ArrValue {509 type Error = LocError;510511 fn try_from(value: Val) -> Result<Self> {512 <Self as Typed>::TYPE.check(&value)?;513 match value {514 Val::Arr(a) => Ok(a),515 _ => unreachable!(),516 }517 }518}519impl TryFrom<ArrValue> for Val {520 type Error = LocError;521522 fn try_from(value: ArrValue) -> Result<Self> {523 Ok(Self::Arr(value))524 }525}526527impl Typed for FuncVal {528 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);529}530impl TryFrom<Val> for FuncVal {531 type Error = LocError;532533 fn try_from(value: Val) -> Result<Self> {534 <Self as Typed>::TYPE.check(&value)?;535 match value {536 Val::Func(a) => Ok(a),537 _ => unreachable!(),538 }539 }540}541impl TryFrom<FuncVal> for Val {542 type Error = LocError;543544 fn try_from(value: FuncVal) -> Result<Self> {545 Ok(Self::Func(value))546 }547}548549impl Typed for Cc<FuncDesc> {550 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);551}552impl TryFrom<Val> for Cc<FuncDesc> {553 type Error = LocError;554555 fn try_from(value: Val) -> Result<Self, Self::Error> {556 <Self as Typed>::TYPE.check(&value)?;557 match value {558 Val::Func(FuncVal::Normal(desc)) => Ok(desc),559 Val::Func(_) => throw!(RuntimeError("expected normal function, not builtin".into())),560 _ => unreachable!(),561 }562 }563}564impl TryFrom<Cc<FuncDesc>> for Val {565 type Error = LocError;566567 fn try_from(value: Cc<FuncDesc>) -> Result<Self, Self::Error> {568 Ok(Self::Func(FuncVal::Normal(value)))569 }570}571572impl Typed for ObjValue {573 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Obj);574}575impl TryFrom<Val> for ObjValue {576 type Error = LocError;577578 fn try_from(value: Val) -> Result<Self> {579 <Self as Typed>::TYPE.check(&value)?;580 match value {581 Val::Obj(a) => Ok(a),582 _ => unreachable!(),583 }584 }585}586impl TryFrom<ObjValue> for Val {587 type Error = LocError;588589 fn try_from(value: ObjValue) -> Result<Self> {590 Ok(Self::Obj(value))591 }592}593594impl Typed for bool {595 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Bool);596}597impl TryFrom<Val> for bool {598 type Error = LocError;599600 fn try_from(value: Val) -> Result<Self> {601 <Self as Typed>::TYPE.check(&value)?;602 match value {603 Val::Bool(a) => Ok(a),604 _ => unreachable!(),605 }606 }607}608impl TryFrom<bool> for Val {609 type Error = LocError;610611 fn try_from(value: bool) -> Result<Self> {612 Ok(Self::Bool(value))613 }614}615616impl Typed for IndexableVal {617 const TYPE: &'static ComplexValType = &ComplexValType::UnionRef(&[618 &ComplexValType::Simple(ValType::Arr),619 &ComplexValType::Simple(ValType::Str),620 ]);621}622impl TryFrom<Val> for IndexableVal {623 type Error = LocError;624625 fn try_from(value: Val) -> Result<Self> {626 <Self as Typed>::TYPE.check(&value)?;627 value.into_indexable()628 }629}630impl TryFrom<IndexableVal> for Val {631 type Error = LocError;632633 fn try_from(value: IndexableVal) -> Result<Self> {634 match value {635 IndexableVal::Str(s) => Ok(Self::Str(s)),636 IndexableVal::Arr(a) => Ok(Self::Arr(a)),637 }638 }639}640641pub struct Null;642impl Typed for Null {643 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Null);644}645impl TryFrom<Val> for Null {646 type Error = LocError;647648 fn try_from(value: Val) -> Result<Self> {649 <Self as Typed>::TYPE.check(&value)?;650 Ok(Self)651 }652}653impl TryFrom<Null> for Val {654 type Error = LocError;655656 fn try_from(_: Null) -> Result<Self> {657 Ok(Self::Null)658 }659}crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -172,6 +172,37 @@
}
#[derive(Debug, Clone, Trace)]
+pub struct Slice {
+ pub(crate) inner: ArrValue,
+ pub(crate) from: u32,
+ pub(crate) to: u32,
+ pub(crate) step: u32,
+}
+impl Slice {
+ fn from(&self) -> usize {
+ self.from as usize
+ }
+ fn to(&self) -> usize {
+ self.to as usize
+ }
+ fn step(&self) -> usize {
+ self.step as usize
+ }
+ fn len(&self) -> usize {
+ // TODO: use div_ceil
+ let diff = self.to() - self.from();
+ let rem = diff % self.step();
+ let div = diff / self.step();
+
+ if rem != 0 {
+ div + 1
+ } else {
+ div
+ }
+ }
+}
+
+#[derive(Debug, Clone, Trace)]
#[force_tracking]
pub enum ArrValue {
Bytes(#[skip_trace] Rc<[u8]>),
@@ -179,6 +210,7 @@
Eager(Cc<Vec<Val>>),
Extended(Box<(Self, Self)>),
Range(i32, i32),
+ Slice(Box<Slice>),
Reversed(Box<Self>),
}
impl ArrValue {
@@ -190,6 +222,22 @@
Self::Range(a, b)
}
+ pub fn slice(self, from: Option<usize>, to: Option<usize>, step: Option<usize>) -> Self {
+ let len = self.len();
+ let from = from.unwrap_or(0);
+ let to = to.unwrap_or(len).min(len);
+ let step = step.unwrap_or(1);
+ assert!(from < to);
+ assert!(step > 0);
+
+ Self::Slice(Box::new(Slice {
+ inner: self,
+ from: from as u32,
+ to: to as u32,
+ step: step as u32,
+ }))
+ }
+
pub fn len(&self) -> usize {
match self {
Self::Bytes(i) => i.len(),
@@ -198,6 +246,7 @@
Self::Extended(v) => v.0.len() + v.1.len(),
Self::Range(a, b) => a.abs_diff(*b) as usize,
Self::Reversed(i) => i.len(),
+ Self::Slice(s) => s.len(),
}
}
@@ -239,6 +288,13 @@
}
v.get(len - index - 1)
}
+ Self::Slice(s) => {
+ let index = s.from() + index * s.step();
+ if index >= s.to() {
+ return Ok(None);
+ }
+ s.inner.get(index as usize)
+ }
}
}
@@ -272,6 +328,13 @@
}
v.get_lazy(len - index - 1)
}
+ Self::Slice(s) => {
+ let index = s.from() + index * s.step();
+ if index >= s.to() {
+ return None;
+ }
+ s.inner.get_lazy(index as usize)
+ }
}
}
@@ -311,33 +374,43 @@
Cc::update_with(&mut r, |v| v.reverse());
r
}
+ Self::Slice(v) => {
+ let mut out = Vec::with_capacity(v.inner.len());
+ for v in v
+ .inner
+ .iter_lazy()
+ .skip(v.from())
+ .take(v.to() - v.from())
+ .step_by(v.step())
+ {
+ out.push(v.evaluate()?)
+ }
+ Cc::new(out)
+ }
})
}
pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {
- // if let Self::Reversed(v) = self {
- // return v.iter().rev();
- // }
- let len = self.len();
- (0..len).map(move |idx| match self {
+ (0..self.len()).map(move |idx| match self {
Self::Bytes(b) => Ok(Val::Num(b[idx] as f64)),
Self::Lazy(l) => l[idx].evaluate(),
Self::Eager(e) => Ok(e[idx].clone()),
Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),
Self::Range(..) => self.get(idx).map(|e| e.unwrap()),
- Self::Reversed(..) => self.get(len - idx - 1).map(|e| e.unwrap()),
+ Self::Reversed(..) => self.get(idx).map(|e| e.unwrap()),
+ Self::Slice(..) => self.get(idx).map(|e| e.unwrap()),
})
}
pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {
- let len = self.len();
- (0..len).map(move |idx| match self {
+ (0..self.len()).map(move |idx| match self {
Self::Bytes(b) => LazyVal::new_resolved(Val::Num(b[idx] as f64)),
Self::Lazy(l) => l[idx].clone(),
Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),
Self::Extended(_) => self.get_lazy(idx).unwrap(),
Self::Range(..) => self.get_lazy(idx).unwrap(),
- Self::Reversed(..) => self.get_lazy(len - idx - 1).unwrap(),
+ Self::Reversed(..) => self.get_lazy(idx).unwrap(),
+ Self::Slice(..) => self.get_lazy(idx).unwrap(),
})
}
@@ -459,17 +532,6 @@
}
}
- pub fn try_cast_nullable_num(self, context: &'static str) -> Result<Option<f64>> {
- Ok(match self {
- Val::Null => None,
- Val::Num(num) => Some(num),
- _ => throw!(TypeMismatch(
- context,
- vec![ValType::Null, ValType::Num],
- self.value_type()
- )),
- })
- }
pub const fn value_type(&self) -> ValType {
match self {
Self::Str(..) => ValType::Str,