@@ -4,7 +4,7 @@ use super::super::pyobject::{
44use super :: super :: vm:: VirtualMachine ;
55use super :: objint;
66use super :: objtype;
7- use num_bigint:: BigInt ;
7+ use num_bigint:: { BigInt , Sign } ;
88use num_integer:: Integer ;
99use num_traits:: { One , Signed , ToPrimitive , Zero } ;
1010
@@ -27,16 +27,29 @@ impl RangeType {
2727 }
2828
2929 #[ 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 ,
3335 }
36+ }
3437
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 ,
4053 }
4154 }
4255
@@ -75,6 +88,12 @@ pub fn init(context: &PyContext) {
7588 "__getitem__" ,
7689 context. new_rustfunc ( range_getitem) ,
7790 ) ;
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+ ) ;
7897 context. set_attr ( & range_type, "index" , context. new_rustfunc ( range_index) ) ;
7998}
8099
@@ -205,6 +224,34 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
205224 }
206225}
207226
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+
208255fn range_index ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
209256 arg_check ! (
210257 vm,
0 commit comments