From 3ee61c42d34d73a2c3cedcdbca0ef101bdea45ca Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sat, 23 Jul 2022 22:29:26 +0000 Subject: [PATCH] feat(evaluator): `IndexableMap::slice` helper Previously `slice` method was only in `ArrayVal`, and for strings it needed to be implemented manually --- --- a/crates/jrsonnet-evaluator/src/val.rs +++ b/crates/jrsonnet-evaluator/src/val.rs @@ -11,7 +11,9 @@ stdlib::manifest::{ manifest_json_ex, manifest_yaml_ex, ManifestJsonOptions, ManifestType, ManifestYamlOptions, }, - throw, ObjValue, Result, State, Unbound, WeakObjValue, + throw, + typed::BoundedUsize, + ObjValue, Result, State, Unbound, WeakObjValue, }; pub trait ThunkValue: Trace { @@ -459,6 +461,51 @@ Str(IStr), Arr(ArrValue), } +impl IndexableVal { + pub fn slice( + self, + index: Option>, + end: Option>, + step: Option>, + ) -> Result { + match &self { + 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(Self::Str("".into())); + } + + Ok(Self::Str( + (s.chars() + .skip(index) + .take(end - index) + .step_by(step) + .collect::()) + .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(Self::Arr(ArrValue::new_eager())); + } + + Ok(Self::Arr(ArrValue::Slice(Box::new(Slice { + inner: arr.clone(), + from: index as u32, + to: end as u32, + step: step as u32, + })))) + } + } + } +} #[derive(Debug, Clone, Trace)] pub enum Val { @@ -471,6 +518,15 @@ Func(FuncVal), } +impl From for Val { + fn from(v: IndexableVal) -> Self { + match v { + IndexableVal::Str(s) => Self::Str(s), + IndexableVal::Arr(a) => Self::Arr(a), + } + } +} + #[cfg(target_pointer_width = "64")] static_assertions::assert_eq_size!(Val, [u8; 32]); -- gitstuff