@@ -4,7 +4,7 @@ use super::super::pyobject::{
4
4
use super :: super :: vm:: VirtualMachine ;
5
5
use super :: objint;
6
6
use super :: objtype;
7
- use num_bigint:: BigInt ;
7
+ use num_bigint:: { BigInt , Sign } ;
8
8
use num_integer:: Integer ;
9
9
use num_traits:: { One , Signed , ToPrimitive , Zero } ;
10
10
@@ -27,16 +27,29 @@ impl RangeType {
27
27
}
28
28
29
29
#[ inline]
30
- pub fn index_of ( & self , value : & BigInt ) -> Option < BigInt > {
31
- if value < & self . start || value >= & self . end {
32
- return None ;
30
+ fn offset ( & self , value : & BigInt ) -> Option < BigInt > {
31
+ match self . step . sign ( ) {
32
+ Sign :: Plus if value >= & self . start && value < & self . end => Some ( value - & self . start ) ,
33
+ Sign :: Minus if value <= & self . start && value > & self . end => Some ( & self . start - value) ,
34
+ _ => None ,
33
35
}
36
+ }
34
37
35
- let offset = value - & self . start ;
36
- if offset. is_multiple_of ( & self . step ) {
37
- Some ( offset / & self . step )
38
- } else {
39
- None
38
+ #[ inline]
39
+ pub fn contains ( & self , value : & BigInt ) -> bool {
40
+ match self . offset ( value) {
41
+ Some ( ref offset) => offset. is_multiple_of ( & self . step ) ,
42
+ None => false ,
43
+ }
44
+ }
45
+
46
+ #[ inline]
47
+ pub fn index_of ( & self , value : & BigInt ) -> Option < BigInt > {
48
+ match self . offset ( value) {
49
+ Some ( ref offset) if offset. is_multiple_of ( & self . step ) => {
50
+ Some ( ( offset / & self . step ) . abs ( ) )
51
+ }
52
+ Some ( _) | None => None ,
40
53
}
41
54
}
42
55
@@ -75,6 +88,12 @@ pub fn init(context: &PyContext) {
75
88
"__getitem__" ,
76
89
context. new_rustfunc ( range_getitem) ,
77
90
) ;
91
+ context. set_attr ( & range_type, "__bool__" , context. new_rustfunc ( range_bool) ) ;
92
+ context. set_attr (
93
+ & range_type,
94
+ "__contains__" ,
95
+ context. new_rustfunc ( range_contains) ,
96
+ ) ;
78
97
context. set_attr ( & range_type, "index" , context. new_rustfunc ( range_index) ) ;
79
98
}
80
99
@@ -205,6 +224,34 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
205
224
}
206
225
}
207
226
227
+ fn range_bool ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
228
+ arg_check ! ( vm, args, required = [ ( zelf, Some ( vm. ctx. range_type( ) ) ) ] ) ;
229
+
230
+ let len = match zelf. borrow ( ) . payload {
231
+ PyObjectPayload :: Range { ref range } => range. len ( ) ,
232
+ _ => unreachable ! ( ) ,
233
+ } ;
234
+
235
+ Ok ( vm. ctx . new_bool ( len > 0 ) )
236
+ }
237
+
238
+ fn range_contains ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
239
+ arg_check ! (
240
+ vm,
241
+ args,
242
+ required = [ ( zelf, Some ( vm. ctx. range_type( ) ) ) , ( needle, None ) ]
243
+ ) ;
244
+
245
+ if let PyObjectPayload :: Range { ref range } = zelf. borrow ( ) . payload {
246
+ Ok ( vm. ctx . new_bool ( match needle. borrow ( ) . payload {
247
+ PyObjectPayload :: Integer { ref value } => range. contains ( value) ,
248
+ _ => false ,
249
+ } ) )
250
+ } else {
251
+ unreachable ! ( )
252
+ }
253
+ }
254
+
208
255
fn range_index ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
209
256
arg_check ! (
210
257
vm,
0 commit comments