1
- use std:: cell:: RefCell ;
1
+ use std:: cell:: { Cell , RefCell } ;
2
2
use std:: cmp:: Ordering ;
3
3
use std:: ops:: { AddAssign , SubAssign } ;
4
4
@@ -12,7 +12,7 @@ use crate::obj::objint::{PyInt, PyIntRef};
12
12
use crate :: obj:: objiter:: { call_next, get_iter, new_stop_iteration} ;
13
13
use crate :: obj:: objtype;
14
14
use crate :: obj:: objtype:: PyClassRef ;
15
- use crate :: pyobject:: { IdProtocol , PyClassImpl , PyObjectRef , PyRef , PyResult , PyValue } ;
15
+ use crate :: pyobject:: { IdProtocol , PyCallable , PyClassImpl , PyObjectRef , PyRef , PyResult , PyValue } ;
16
16
use crate :: vm:: VirtualMachine ;
17
17
18
18
#[ pyclass( name = "chain" ) ]
@@ -290,6 +290,67 @@ impl PyItertoolsTakewhile {
290
290
}
291
291
}
292
292
293
+ #[ pyclass]
294
+ #[ derive( Debug ) ]
295
+ struct PyItertoolsDropwhile {
296
+ predicate : PyCallable ,
297
+ iterable : PyObjectRef ,
298
+ start_flag : Cell < bool > ,
299
+ }
300
+
301
+ impl PyValue for PyItertoolsDropwhile {
302
+ fn class ( vm : & VirtualMachine ) -> PyClassRef {
303
+ vm. class ( "itertools" , "dropwhile" )
304
+ }
305
+ }
306
+
307
+ type PyItertoolsDropwhileRef = PyRef < PyItertoolsDropwhile > ;
308
+
309
+ #[ pyimpl]
310
+ impl PyItertoolsDropwhile {
311
+ #[ pymethod( name = "__new__" ) ]
312
+ #[ allow( clippy:: new_ret_no_self) ]
313
+ fn new (
314
+ cls : PyClassRef ,
315
+ predicate : PyCallable ,
316
+ iterable : PyObjectRef ,
317
+ vm : & VirtualMachine ,
318
+ ) -> PyResult < PyItertoolsDropwhileRef > {
319
+ let iter = get_iter ( vm, & iterable) ?;
320
+
321
+ PyItertoolsDropwhile {
322
+ predicate,
323
+ iterable : iter,
324
+ start_flag : Cell :: new ( false ) ,
325
+ }
326
+ . into_ref_with_type ( vm, cls)
327
+ }
328
+
329
+ #[ pymethod( name = "__next__" ) ]
330
+ fn next ( & self , vm : & VirtualMachine ) -> PyResult {
331
+ let predicate = & self . predicate ;
332
+ let iterable = & self . iterable ;
333
+
334
+ if !self . start_flag . get ( ) {
335
+ loop {
336
+ let obj = call_next ( vm, iterable) ?;
337
+ let pred = predicate. clone ( ) ;
338
+ let pred_value = vm. invoke ( & pred. into_object ( ) , vec ! [ obj. clone( ) ] ) ?;
339
+ if !objbool:: boolval ( vm, pred_value) ? {
340
+ self . start_flag . set ( true ) ;
341
+ return Ok ( obj) ;
342
+ }
343
+ }
344
+ }
345
+ call_next ( vm, iterable)
346
+ }
347
+
348
+ #[ pymethod( name = "__iter__" ) ]
349
+ fn iter ( zelf : PyRef < Self > , _vm : & VirtualMachine ) -> PyRef < Self > {
350
+ zelf
351
+ }
352
+ }
353
+
293
354
#[ pyclass( name = "islice" ) ]
294
355
#[ derive( Debug ) ]
295
356
struct PyItertoolsIslice {
@@ -484,6 +545,9 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
484
545
let count = ctx. new_class ( "count" , ctx. object ( ) ) ;
485
546
PyItertoolsCount :: extend_class ( ctx, & count) ;
486
547
548
+ let dropwhile = ctx. new_class ( "dropwhile" , ctx. object ( ) ) ;
549
+ PyItertoolsDropwhile :: extend_class ( ctx, & dropwhile) ;
550
+
487
551
let repeat = ctx. new_class ( "repeat" , ctx. object ( ) ) ;
488
552
PyItertoolsRepeat :: extend_class ( ctx, & repeat) ;
489
553
@@ -500,6 +564,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
500
564
py_module ! ( vm, "itertools" , {
501
565
"chain" => chain,
502
566
"count" => count,
567
+ "dropwhile" => dropwhile,
503
568
"repeat" => repeat,
504
569
"starmap" => starmap,
505
570
"takewhile" => takewhile,
0 commit comments