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}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,