1
+ use std:: cell:: RefCell ;
1
2
use std:: fs:: File ;
2
3
use std:: fs:: OpenOptions ;
3
4
use std:: io:: { ErrorKind , Read , Write } ;
@@ -10,9 +11,11 @@ use crate::obj::objbytes::PyBytesRef;
10
11
use crate :: obj:: objdict:: PyDictRef ;
11
12
use crate :: obj:: objint;
12
13
use crate :: obj:: objint:: PyIntRef ;
14
+ use crate :: obj:: objiter;
13
15
use crate :: obj:: objstr;
14
16
use crate :: obj:: objstr:: PyStringRef ;
15
- use crate :: pyobject:: { ItemProtocol , PyObjectRef , PyResult } ;
17
+ use crate :: obj:: objtype:: PyClassRef ;
18
+ use crate :: pyobject:: { ItemProtocol , PyObjectRef , PyRef , PyResult , PyValue } ;
16
19
use crate :: vm:: VirtualMachine ;
17
20
18
21
#[ cfg( unix) ]
@@ -190,6 +193,65 @@ fn _os_environ(vm: &VirtualMachine) -> PyDictRef {
190
193
environ
191
194
}
192
195
196
+ #[ derive( Debug ) ]
197
+ struct DirEntry {
198
+ entry : fs:: DirEntry ,
199
+ }
200
+
201
+ type DirEntryRef = PyRef < DirEntry > ;
202
+
203
+ impl PyValue for DirEntry {
204
+ fn class ( vm : & VirtualMachine ) -> PyClassRef {
205
+ vm. class ( "os" , "DirEntry" )
206
+ }
207
+ }
208
+
209
+ impl DirEntryRef {
210
+ fn name ( self , _vm : & VirtualMachine ) -> String {
211
+ self . entry . file_name ( ) . into_string ( ) . unwrap ( )
212
+ }
213
+ }
214
+
215
+ #[ derive( Debug ) ]
216
+ pub struct ScandirIterator {
217
+ entries : RefCell < fs:: ReadDir > ,
218
+ }
219
+
220
+ impl PyValue for ScandirIterator {
221
+ fn class ( vm : & VirtualMachine ) -> PyClassRef {
222
+ vm. class ( "os" , "ScandirIter" )
223
+ }
224
+ }
225
+
226
+ type ScandirIteratorRef = PyRef < ScandirIterator > ;
227
+
228
+ impl ScandirIteratorRef {
229
+ fn next ( self , vm : & VirtualMachine ) -> PyResult {
230
+ match self . entries . borrow_mut ( ) . next ( ) {
231
+ Some ( entry) => match entry {
232
+ Ok ( entry) => Ok ( DirEntry { entry } . into_ref ( vm) . into_object ( ) ) ,
233
+ Err ( s) => Err ( vm. new_os_error ( s. to_string ( ) ) ) ,
234
+ } ,
235
+ None => Err ( objiter:: new_stop_iteration ( vm) ) ,
236
+ }
237
+ }
238
+
239
+ fn iter ( self , _vm : & VirtualMachine ) -> Self {
240
+ self
241
+ }
242
+ }
243
+
244
+ fn os_scandir ( path : PyStringRef , vm : & VirtualMachine ) -> PyResult {
245
+ match fs:: read_dir ( & path. value ) {
246
+ Ok ( iter) => Ok ( ScandirIterator {
247
+ entries : RefCell :: new ( iter) ,
248
+ }
249
+ . into_ref ( vm)
250
+ . into_object ( ) ) ,
251
+ Err ( s) => Err ( vm. new_os_error ( s. to_string ( ) ) ) ,
252
+ }
253
+ }
254
+
193
255
pub fn make_module ( vm : & VirtualMachine ) -> PyObjectRef {
194
256
let ctx = & vm. ctx ;
195
257
@@ -201,6 +263,15 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
201
263
202
264
let environ = _os_environ ( vm) ;
203
265
266
+ let scandir_iter = py_class ! ( ctx, "ScandirIter" , ctx. object( ) , {
267
+ "__iter__" => ctx. new_rustfunc( ScandirIteratorRef :: iter) ,
268
+ "__next__" => ctx. new_rustfunc( ScandirIteratorRef :: next) ,
269
+ } ) ;
270
+
271
+ let dir_entry = py_class ! ( ctx, "DirEntry" , ctx. object( ) , {
272
+ "name" => ctx. new_rustfunc( DirEntryRef :: name) ,
273
+ } ) ;
274
+
204
275
py_module ! ( vm, "_os" , {
205
276
"open" => ctx. new_rustfunc( os_open) ,
206
277
"close" => ctx. new_rustfunc( os_close) ,
@@ -217,6 +288,9 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
217
288
"unsetenv" => ctx. new_rustfunc( os_unsetenv) ,
218
289
"environ" => environ,
219
290
"name" => ctx. new_str( os_name) ,
291
+ "scandir" => ctx. new_rustfunc( os_scandir) ,
292
+ "ScandirIter" => scandir_iter,
293
+ "DirEntry" => dir_entry,
220
294
"O_RDONLY" => ctx. new_int( 0 ) ,
221
295
"O_WRONLY" => ctx. new_int( 1 ) ,
222
296
"O_RDWR" => ctx. new_int( 2 ) ,
0 commit comments