1
- use crate :: stream:: TryStreamExt ;
2
1
use core:: pin:: Pin ;
3
2
use futures_core:: ready;
4
3
use futures_core:: stream:: TryStream ;
5
4
use futures_core:: task:: { Context , Poll } ;
6
5
use futures_io:: { AsyncBufRead , AsyncRead , AsyncWrite } ;
6
+ use pin_project_lite:: pin_project;
7
7
use std:: cmp;
8
8
use std:: io:: { Error , Result } ;
9
9
10
- /// Reader for the [`into_async_read`](super::TryStreamExt::into_async_read) method.
11
- #[ derive( Debug ) ]
12
- #[ must_use = "readers do nothing unless polled" ]
13
- #[ cfg_attr( docsrs, doc( cfg( feature = "io" ) ) ) ]
14
- pub struct IntoAsyncRead < St >
15
- where
16
- St : TryStream < Error = Error > + Unpin ,
17
- St :: Ok : AsRef < [ u8 ] > ,
18
- {
19
- stream : St ,
20
- state : ReadState < St :: Ok > ,
21
- }
22
-
23
- impl < St > Unpin for IntoAsyncRead < St >
24
- where
25
- St : TryStream < Error = Error > + Unpin ,
26
- St :: Ok : AsRef < [ u8 ] > ,
27
- {
10
+ pin_project ! {
11
+ /// Reader for the [`into_async_read`](super::TryStreamExt::into_async_read) method.
12
+ #[ derive( Debug ) ]
13
+ #[ must_use = "readers do nothing unless polled" ]
14
+ #[ cfg_attr( docsrs, doc( cfg( feature = "io" ) ) ) ]
15
+ pub struct IntoAsyncRead <St >
16
+ where
17
+ St : TryStream <Error = Error >,
18
+ St :: Ok : AsRef <[ u8 ] >,
19
+ {
20
+ #[ pin]
21
+ stream: St ,
22
+ state: ReadState <St :: Ok >,
23
+ }
28
24
}
29
25
30
26
#[ derive( Debug ) ]
@@ -36,7 +32,7 @@ enum ReadState<T: AsRef<[u8]>> {
36
32
37
33
impl < St > IntoAsyncRead < St >
38
34
where
39
- St : TryStream < Error = Error > + Unpin ,
35
+ St : TryStream < Error = Error > ,
40
36
St :: Ok : AsRef < [ u8 ] > ,
41
37
{
42
38
pub ( super ) fn new ( stream : St ) -> Self {
@@ -46,16 +42,18 @@ where
46
42
47
43
impl < St > AsyncRead for IntoAsyncRead < St >
48
44
where
49
- St : TryStream < Error = Error > + Unpin ,
45
+ St : TryStream < Error = Error > ,
50
46
St :: Ok : AsRef < [ u8 ] > ,
51
47
{
52
48
fn poll_read (
53
- mut self : Pin < & mut Self > ,
49
+ self : Pin < & mut Self > ,
54
50
cx : & mut Context < ' _ > ,
55
51
buf : & mut [ u8 ] ,
56
52
) -> Poll < Result < usize > > {
53
+ let mut this = self . project ( ) ;
54
+
57
55
loop {
58
- match & mut self . state {
56
+ match this . state {
59
57
ReadState :: Ready { chunk, chunk_start } => {
60
58
let chunk = chunk. as_ref ( ) ;
61
59
let len = cmp:: min ( buf. len ( ) , chunk. len ( ) - * chunk_start) ;
@@ -64,23 +62,23 @@ where
64
62
* chunk_start += len;
65
63
66
64
if chunk. len ( ) == * chunk_start {
67
- self . state = ReadState :: PendingChunk ;
65
+ * this . state = ReadState :: PendingChunk ;
68
66
}
69
67
70
68
return Poll :: Ready ( Ok ( len) ) ;
71
69
}
72
- ReadState :: PendingChunk => match ready ! ( self . stream. try_poll_next_unpin ( cx) ) {
70
+ ReadState :: PendingChunk => match ready ! ( this . stream. as_mut ( ) . try_poll_next ( cx) ) {
73
71
Some ( Ok ( chunk) ) => {
74
72
if !chunk. as_ref ( ) . is_empty ( ) {
75
- self . state = ReadState :: Ready { chunk, chunk_start : 0 } ;
73
+ * this . state = ReadState :: Ready { chunk, chunk_start : 0 } ;
76
74
}
77
75
}
78
76
Some ( Err ( err) ) => {
79
- self . state = ReadState :: Eof ;
77
+ * this . state = ReadState :: Eof ;
80
78
return Poll :: Ready ( Err ( err) ) ;
81
79
}
82
80
None => {
83
- self . state = ReadState :: Eof ;
81
+ * this . state = ReadState :: Eof ;
84
82
return Poll :: Ready ( Ok ( 0 ) ) ;
85
83
}
86
84
} ,
@@ -94,51 +92,52 @@ where
94
92
95
93
impl < St > AsyncWrite for IntoAsyncRead < St >
96
94
where
97
- St : TryStream < Error = Error > + AsyncWrite + Unpin ,
95
+ St : TryStream < Error = Error > + AsyncWrite ,
98
96
St :: Ok : AsRef < [ u8 ] > ,
99
97
{
100
- fn poll_write (
101
- mut self : Pin < & mut Self > ,
102
- cx : & mut Context < ' _ > ,
103
- buf : & [ u8 ] ,
104
- ) -> Poll < Result < usize > > {
105
- Pin :: new ( & mut self . stream ) . poll_write ( cx, buf)
98
+ fn poll_write ( self : Pin < & mut Self > , cx : & mut Context < ' _ > , buf : & [ u8 ] ) -> Poll < Result < usize > > {
99
+ let this = self . project ( ) ;
100
+ this. stream . poll_write ( cx, buf)
106
101
}
107
102
108
- fn poll_flush ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) > > {
109
- Pin :: new ( & mut self . stream ) . poll_flush ( cx)
103
+ fn poll_flush ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) > > {
104
+ let this = self . project ( ) ;
105
+ this. stream . poll_flush ( cx)
110
106
}
111
107
112
- fn poll_close ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) > > {
113
- Pin :: new ( & mut self . stream ) . poll_close ( cx)
108
+ fn poll_close ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) > > {
109
+ let this = self . project ( ) ;
110
+ this. stream . poll_close ( cx)
114
111
}
115
112
}
116
113
117
114
impl < St > AsyncBufRead for IntoAsyncRead < St >
118
115
where
119
- St : TryStream < Error = Error > + Unpin ,
116
+ St : TryStream < Error = Error > ,
120
117
St :: Ok : AsRef < [ u8 ] > ,
121
118
{
122
- fn poll_fill_buf ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < & [ u8 ] > > {
123
- while let ReadState :: PendingChunk = self . state {
124
- match ready ! ( self . stream. try_poll_next_unpin( cx) ) {
119
+ fn poll_fill_buf ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < & [ u8 ] > > {
120
+ let mut this = self . project ( ) ;
121
+
122
+ while let ReadState :: PendingChunk = this. state {
123
+ match ready ! ( this. stream. as_mut( ) . try_poll_next( cx) ) {
125
124
Some ( Ok ( chunk) ) => {
126
125
if !chunk. as_ref ( ) . is_empty ( ) {
127
- self . state = ReadState :: Ready { chunk, chunk_start : 0 } ;
126
+ * this . state = ReadState :: Ready { chunk, chunk_start : 0 } ;
128
127
}
129
128
}
130
129
Some ( Err ( err) ) => {
131
- self . state = ReadState :: Eof ;
130
+ * this . state = ReadState :: Eof ;
132
131
return Poll :: Ready ( Err ( err) ) ;
133
132
}
134
133
None => {
135
- self . state = ReadState :: Eof ;
134
+ * this . state = ReadState :: Eof ;
136
135
return Poll :: Ready ( Ok ( & [ ] ) ) ;
137
136
}
138
137
}
139
138
}
140
139
141
- if let ReadState :: Ready { ref chunk, chunk_start } = self . into_ref ( ) . get_ref ( ) . state {
140
+ if let & mut ReadState :: Ready { ref chunk, chunk_start } = this . state {
142
141
let chunk = chunk. as_ref ( ) ;
143
142
return Poll :: Ready ( Ok ( & chunk[ chunk_start..] ) ) ;
144
143
}
@@ -147,16 +146,18 @@ where
147
146
Poll :: Ready ( Ok ( & [ ] ) )
148
147
}
149
148
150
- fn consume ( mut self : Pin < & mut Self > , amount : usize ) {
149
+ fn consume ( self : Pin < & mut Self > , amount : usize ) {
150
+ let this = self . project ( ) ;
151
+
151
152
// https://github.com/rust-lang/futures-rs/pull/1556#discussion_r281644295
152
153
if amount == 0 {
153
154
return ;
154
155
}
155
- if let ReadState :: Ready { chunk, chunk_start } = & mut self . state {
156
+ if let ReadState :: Ready { chunk, chunk_start } = this . state {
156
157
* chunk_start += amount;
157
158
debug_assert ! ( * chunk_start <= chunk. as_ref( ) . len( ) ) ;
158
159
if * chunk_start >= chunk. as_ref ( ) . len ( ) {
159
- self . state = ReadState :: PendingChunk ;
160
+ * this . state = ReadState :: PendingChunk ;
160
161
}
161
162
} else {
162
163
debug_assert ! ( false , "Attempted to consume from IntoAsyncRead without chunk" ) ;
0 commit comments