@@ -234,14 +234,34 @@ impl IndexableVal {
234
234
/// For arrays, nothing will be copied on this call, instead [`ArrValue::Slice`] view will be returned.
235
235
pub fn slice (
236
236
self ,
237
- index : Option < BoundedUsize < 0 , { i32:: MAX as usize } > > ,
238
- end : Option < BoundedUsize < 0 , { i32:: MAX as usize } > > ,
237
+ index : Option < i32 > ,
238
+ end : Option < i32 > ,
239
239
step : Option < BoundedUsize < 1 , { i32:: MAX as usize } > > ,
240
240
) -> Result < Self > {
241
241
match & self {
242
242
IndexableVal :: Str ( s) => {
243
- let index = index. as_deref ( ) . copied ( ) . unwrap_or ( 0 ) ;
244
- let end = end. as_deref ( ) . copied ( ) . unwrap_or ( usize:: MAX ) ;
243
+ let mut computed_len = None ;
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 ) ;
264
+ let end = get_idx ( end, usize:: MAX ) ;
245
265
let step = step. as_deref ( ) . copied ( ) . unwrap_or ( 1 ) ;
246
266
247
267
if index >= end {
@@ -258,8 +278,13 @@ impl IndexableVal {
258
278
) )
259
279
}
260
280
IndexableVal :: Arr ( arr) => {
261
- let index = index. as_deref ( ) . copied ( ) . unwrap_or ( 0 ) ;
262
- let end = end. as_deref ( ) . copied ( ) . unwrap_or ( usize:: MAX ) . min ( arr. len ( ) ) ;
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 ) ;
287
+ let end = get_idx ( end, arr. len ( ) , arr. len ( ) ) ;
263
288
let step = step. as_deref ( ) . copied ( ) . unwrap_or ( 1 ) ;
264
289
265
290
if index >= end {
0 commit comments