@@ -33,11 +33,11 @@ const CHUNK_SIZE: usize = 32;
33
33
pub async fn read_dir ( path : impl AsRef < Path > ) -> io:: Result < ReadDir > {
34
34
let path = path. as_ref ( ) . to_owned ( ) ;
35
35
asyncify ( || -> io:: Result < ReadDir > {
36
- let mut std = std:: fs:: read_dir ( path) ?. fuse ( ) ;
36
+ let mut std = std:: fs:: read_dir ( path) ?;
37
37
let mut buf = VecDeque :: with_capacity ( CHUNK_SIZE ) ;
38
- ReadDir :: next_chunk ( & mut buf, & mut std) ;
38
+ let remain = ReadDir :: next_chunk ( & mut buf, & mut std) ;
39
39
40
- Ok ( ReadDir ( State :: Idle ( Some ( ( buf, std) ) ) ) )
40
+ Ok ( ReadDir ( State :: Idle ( Some ( ( buf, std, remain ) ) ) ) )
41
41
} )
42
42
. await
43
43
}
@@ -64,12 +64,10 @@ pub async fn read_dir(path: impl AsRef<Path>) -> io::Result<ReadDir> {
64
64
#[ must_use = "streams do nothing unless polled" ]
65
65
pub struct ReadDir ( State ) ;
66
66
67
- type StdReadDir = std:: iter:: Fuse < std:: fs:: ReadDir > ;
68
-
69
67
#[ derive( Debug ) ]
70
68
enum State {
71
- Idle ( Option < ( VecDeque < io:: Result < DirEntry > > , StdReadDir ) > ) ,
72
- Pending ( JoinHandle < ( VecDeque < io:: Result < DirEntry > > , StdReadDir ) > ) ,
69
+ Idle ( Option < ( VecDeque < io:: Result < DirEntry > > , std :: fs :: ReadDir , bool ) > ) ,
70
+ Pending ( JoinHandle < ( VecDeque < io:: Result < DirEntry > > , std :: fs :: ReadDir , bool ) > ) ,
73
71
}
74
72
75
73
impl ReadDir {
@@ -105,38 +103,35 @@ impl ReadDir {
105
103
loop {
106
104
match self . 0 {
107
105
State :: Idle ( ref mut data) => {
108
- let ( buf, _) = data. as_mut ( ) . unwrap ( ) ;
106
+ let ( buf, _, ref remain ) = data. as_mut ( ) . unwrap ( ) ;
109
107
110
108
if let Some ( ent) = buf. pop_front ( ) {
111
109
return Poll :: Ready ( ent. map ( Some ) ) ;
112
- } ;
110
+ } else if !remain {
111
+ return Poll :: Ready ( Ok ( None ) ) ;
112
+ }
113
113
114
- let ( mut buf, mut std) = data. take ( ) . unwrap ( ) ;
114
+ let ( mut buf, mut std, _ ) = data. take ( ) . unwrap ( ) ;
115
115
116
116
self . 0 = State :: Pending ( spawn_blocking ( move || {
117
- ReadDir :: next_chunk ( & mut buf, & mut std) ;
118
- ( buf, std)
117
+ let remain = ReadDir :: next_chunk ( & mut buf, & mut std) ;
118
+ ( buf, std, remain )
119
119
} ) ) ;
120
120
}
121
121
State :: Pending ( ref mut rx) => {
122
- let ( mut buf, std) = ready ! ( Pin :: new( rx) . poll( cx) ) ?;
123
-
124
- let ret = match buf. pop_front ( ) {
125
- Some ( Ok ( x) ) => Ok ( Some ( x) ) ,
126
- Some ( Err ( e) ) => Err ( e) ,
127
- None => Ok ( None ) ,
128
- } ;
129
-
130
- self . 0 = State :: Idle ( Some ( ( buf, std) ) ) ;
131
-
132
- return Poll :: Ready ( ret) ;
122
+ self . 0 = State :: Idle ( Some ( ready ! ( Pin :: new( rx) . poll( cx) ) ?) ) ;
133
123
}
134
124
}
135
125
}
136
126
}
137
127
138
- fn next_chunk ( buf : & mut VecDeque < io:: Result < DirEntry > > , std : & mut StdReadDir ) {
139
- for ret in std. by_ref ( ) . take ( CHUNK_SIZE ) {
128
+ fn next_chunk ( buf : & mut VecDeque < io:: Result < DirEntry > > , std : & mut std:: fs:: ReadDir ) -> bool {
129
+ for _ in 0 ..CHUNK_SIZE {
130
+ let ret = match std. next ( ) {
131
+ Some ( ret) => ret,
132
+ None => return false ,
133
+ } ;
134
+
140
135
let success = ret. is_ok ( ) ;
141
136
142
137
buf. push_back ( ret. map ( |std| DirEntry {
@@ -154,6 +149,8 @@ impl ReadDir {
154
149
break ;
155
150
}
156
151
}
152
+
153
+ true
157
154
}
158
155
}
159
156
0 commit comments