@@ -62,10 +62,11 @@ pub fn coerce<'x>(a: &'x Value, b: &'x Value, lossy: bool) -> Option<CoerceResul
62
62
}
63
63
64
64
fn get_offset_and_len < F : FnOnce ( ) -> usize > (
65
- start : i64 ,
65
+ start : Option < i64 > ,
66
66
stop : Option < i64 > ,
67
67
end : F ,
68
68
) -> ( usize , usize ) {
69
+ let start = start. unwrap_or ( 0 ) ;
69
70
if start < 0 || stop. map_or ( true , |x| x < 0 ) {
70
71
let end = end ( ) ;
71
72
let start = if start < 0 {
@@ -88,22 +89,16 @@ fn get_offset_and_len<F: FnOnce() -> usize>(
88
89
}
89
90
90
91
fn range_step_backwards (
91
- start_was_none : bool ,
92
- start : i64 ,
92
+ start : Option < i64 > ,
93
93
stop : Option < i64 > ,
94
94
step : usize ,
95
95
end : usize ,
96
96
) -> impl Iterator < Item = usize > {
97
- let start = if start_was_none {
98
- end. saturating_sub ( 1 )
99
- } else if start >= 0 {
100
- if start as usize >= end {
101
- end. saturating_sub ( 1 )
102
- } else {
103
- start as usize
104
- }
105
- } else {
106
- ( end as i64 + start) . max ( 0 ) as usize
97
+ let start = match start {
98
+ None => end. saturating_sub ( 1 ) ,
99
+ Some ( start) if start >= end as i64 => end. saturating_sub ( 1 ) ,
100
+ Some ( start) if start >= 0 => start as usize ,
101
+ Some ( start) => ( end as i64 + start) . max ( 0 ) as usize ,
107
102
} ;
108
103
let stop = match stop {
109
104
None => 0 ,
@@ -115,16 +110,14 @@ fn range_step_backwards(
115
110
} else {
116
111
( start - stop + step - 1 ) / step
117
112
} ;
118
- std :: iter :: successors ( Some ( start) , move | & i| i . checked_sub ( step ) ) . take ( length)
113
+ ( stop..= start) . rev ( ) . step_by ( step ) . take ( length)
119
114
}
120
115
121
116
pub fn slice ( value : Value , start : Value , stop : Value , step : Value ) -> Result < Value , Error > {
122
- let start_was_none = start. is_none ( ) ;
123
-
124
- let start: i64 = if start_was_none {
125
- 0
117
+ let start = if start. is_none ( ) {
118
+ None
126
119
} else {
127
- ok ! ( start. try_into( ) )
120
+ Some ( ok ! ( start. try_into( ) ) )
128
121
} ;
129
122
let stop = if stop. is_none ( ) {
130
123
None
@@ -164,7 +157,7 @@ pub fn slice(value: Value, start: Value, stop: Value, step: Value) -> Result<Val
164
157
} else {
165
158
let chars: Vec < char > = s. chars ( ) . collect ( ) ;
166
159
Ok ( Value :: from (
167
- range_step_backwards ( start_was_none , start, stop, -step as usize , chars. len ( ) )
160
+ range_step_backwards ( start, stop, -step as usize , chars. len ( ) )
168
161
. map ( move |i| chars[ i] )
169
162
. collect :: < String > ( ) ,
170
163
) )
@@ -183,7 +176,7 @@ pub fn slice(value: Value, start: Value, stop: Value, step: Value) -> Result<Val
183
176
) )
184
177
} else {
185
178
Ok ( Value :: from_bytes (
186
- range_step_backwards ( start_was_none , start, stop, -step as usize , b. len ( ) )
179
+ range_step_backwards ( start, stop, -step as usize , b. len ( ) )
187
180
. map ( |i| b[ i] )
188
181
. collect :: < Vec < u8 > > ( ) ,
189
182
) )
@@ -206,14 +199,8 @@ pub fn slice(value: Value, start: Value, stop: Value, step: Value) -> Result<Val
206
199
if let Some ( iter) = obj. try_iter ( ) {
207
200
let vec: Vec < Value > = iter. collect ( ) ;
208
201
Box :: new (
209
- range_step_backwards (
210
- start_was_none,
211
- start,
212
- stop,
213
- -step as usize ,
214
- vec. len ( ) ,
215
- )
216
- . map ( move |i| vec[ i] . clone ( ) ) ,
202
+ range_step_backwards ( start, stop, -step as usize , vec. len ( ) )
203
+ . map ( move |i| vec[ i] . clone ( ) ) ,
217
204
)
218
205
} else {
219
206
Box :: new ( None . into_iter ( ) )
0 commit comments