@@ -44,7 +44,12 @@ pub async fn rmdir(path : StringView, recursive? : Bool = false) -> Unit {
4444
4545///|
4646/// A directory in file system
47- struct Directory (@event_loop .Directory )
47+ #external
48+ type Directory
49+
50+ ///|
51+ #external
52+ priv type DirectoryEntry
4853
4954///|
5055extern "C" fn Directory ::close_ffi (self : Directory ) -> Int = "closedir"
@@ -54,29 +59,68 @@ pub fn Directory::close(self : Directory) -> Unit {
5459 guard self .close_ffi () == 0
5560}
5661
62+ ///|
63+ #borrow (path )
64+ extern "C" fn opendir_ffi (path : Bytes ) -> Directory = "opendir"
65+
66+ ///|
67+ async fn opendir_aux (path : StringView , context ~ : String ) -> Directory {
68+ struct Job {
69+ path : Bytes
70+ mut result : Directory
71+ mut err : Int
72+ }
73+ let path_bytes = @encoding/utf8 .encode (path )
74+ let job : Job = { path : path_bytes , result : @c_buffer .null_ptr (), err : 0 }
75+ @event_loop .perform_job_in_worker (job , job => {
76+ job .result = opendir_ffi (job .path)
77+ job .err = @os_error .get_errno ()
78+ }) catch {
79+ err => {
80+ if !@c_buffer .ptr_is_null (job .result) {
81+ ignore (job .result.close_ffi ())
82+ }
83+ raise err
84+ }
85+ }
86+ if @c_buffer .ptr_is_null (job .result) {
87+ raise @os_error .OSError (job .err, context = "\{ context } : \{ repr (path )} " )
88+ }
89+ job .result
90+ }
91+
5792///|
5893/// Open the directory at `path`. `path` is encoded UTF8.
5994/// If `path` is not a directory, an error will be raised
6095pub async fn opendir (path : StringView ) -> Directory {
61- @event_loop . opendir (path , context = "@fs.opendir()" )
96+ opendir_aux (path , context = "@fs.opendir()" )
6297}
6398
64- ///|
65- using @event_loop {type DirectoryEntry }
66-
6799///|
68100extern "C" fn DirectoryEntry ::name (ent : DirectoryEntry ) -> Bytes = "moonbitlang_async_dirent_name"
69101
70102///|
71- extern "C" fn DirectoryEntry :: is_null ( ent : DirectoryEntry ) -> Bool = "moonbitlang_async_dirent_is_null "
103+ extern "C" fn readdir_ffi ( dir : Directory ) -> DirectoryEntry = "readdir "
72104
73105///|
74106async fn Directory ::read_next (dir : Directory ) -> String? {
75- let dir_ent = @event_loop .readdir (dir .0 , context = "@fs.readdir()" )
76- if dir_ent .is_null () {
107+ struct Job {
108+ dir : Directory
109+ mut result : DirectoryEntry
110+ mut err : Int
111+ }
112+ let job : Job = { dir , result : @c_buffer .null_ptr (), err : 0 }
113+ @event_loop .perform_job_in_worker (job , job => {
114+ @os_error .clear_errno ()
115+ job .result = readdir_ffi (job .dir)
116+ job .err = @os_error .get_errno ()
117+ })
118+ if job .err != 0 {
119+ raise @os_error .OSError (job .err, context = "@fs.readdir()" )
120+ } else if @c_buffer .ptr_is_null (job .result) {
77121 None
78122 } else {
79- Some (@encoding/utf8 .decode (dir_ent .name ()))
123+ Some (@encoding/utf8 .decode (job .result .name ()))
80124 }
81125}
82126
@@ -119,7 +163,7 @@ pub async fn readdir(
119163 include_special ? : Bool = false ,
120164 sort ? : Bool = false ,
121165) -> Array [String ] {
122- let dir : Directory = @event_loop . opendir (path , context = "@fs.readdir()" )
166+ let dir : Directory = opendir_aux (path , context = "@fs.readdir()" )
123167 defer dir .close ()
124168 let list = dir .read_all (include_hidden ~, include_special ~)
125169 if sort {
0 commit comments