git.delta.rocks / jrsonnet / refs/commits / d91bf0e3d51a

difftreelog

feat allow negative indexes in std.slice

Yaroslav Bolyukin2024-03-03parent: #7f29d2d.patch.diff
in: master
Upstream issue: https://github.com/google/jsonnet/pull/1093

2 files changed

modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
234 /// For arrays, nothing will be copied on this call, instead [`ArrValue::Slice`] view will be returned.234 /// For arrays, nothing will be copied on this call, instead [`ArrValue::Slice`] view will be returned.
235 pub fn slice(235 pub fn slice(
236 self,236 self,
237 index: Option<BoundedUsize<0, { i32::MAX as usize }>>,237 index: Option<i32>,
238 end: Option<BoundedUsize<0, { i32::MAX as usize }>>,238 end: Option<i32>,
239 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,239 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,
240 ) -> Result<Self> {240 ) -> Result<Self> {
241 match &self {241 match &self {
242 IndexableVal::Str(s) => {242 IndexableVal::Str(s) => {
243 let mut computed_len = None;
243 let index = index.as_deref().copied().unwrap_or(0);244 let mut get_len = || {
245 computed_len.map_or_else(
246 || {
247 let len = s.chars().count();
248 let _ = computed_len.insert(len);
249 len
250 },
251 |len| len,
252 )
253 };
254 let mut get_idx = |pos: Option<i32>, default| {
255 match pos {
256 Some(v) if v < 0 => get_len().saturating_sub((-v) as usize),
257 // No need to clamp, as iterator interface is used
258 Some(v) => v as usize,
259 None => default,
260 }
261 };
262
263 let index = get_idx(index, 0);
244 let end = end.as_deref().copied().unwrap_or(usize::MAX);264 let end = get_idx(end, usize::MAX);
245 let step = step.as_deref().copied().unwrap_or(1);265 let step = step.as_deref().copied().unwrap_or(1);
246266
247 if index >= end {267 if index >= end {
258 ))278 ))
259 }279 }
260 IndexableVal::Arr(arr) => {280 IndexableVal::Arr(arr) => {
261 let index = index.as_deref().copied().unwrap_or(0);281 let get_idx = |pos: Option<i32>, len: usize, default| match pos {
282 Some(v) if v < 0 => len.saturating_sub((-v) as usize),
283 Some(v) => (v as usize).min(len),
284 None => default,
285 };
286 let index = get_idx(index, arr.len(), 0);
262 let end = end.as_deref().copied().unwrap_or(usize::MAX).min(arr.len());287 let end = get_idx(end, arr.len(), arr.len());
263 let step = step.as_deref().copied().unwrap_or(1);288 let step = step.as_deref().copied().unwrap_or(1);
264289
265 if index >= end {290 if index >= end {
modifiedcrates/jrsonnet-stdlib/src/arrays.rsdiffbeforeafterboth
47#[builtin]47#[builtin]
48pub fn builtin_slice(48pub fn builtin_slice(
49 indexable: IndexableVal,49 indexable: IndexableVal,
50 index: Option<BoundedUsize<0, { i32::MAX as usize }>>,50 index: Option<i32>,
51 end: Option<BoundedUsize<0, { i32::MAX as usize }>>,51 end: Option<i32>,
52 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,52 step: Option<BoundedUsize<1, { i32::MAX as usize }>>,
53) -> Result<Val> {53) -> Result<Val> {
54 indexable.slice(index, end, step).map(Val::from)54 indexable.slice(index, end, step).map(Val::from)