@@ -15,6 +15,8 @@ use crate::date::fmt_http_date;
15
15
/// This is returned from [`encode`].
16
16
#[ derive( Debug ) ]
17
17
pub ( crate ) struct Encoder {
18
+ /// The current level of recursion the encoder is in.
19
+ depth : u16 ,
18
20
/// HTTP headers to be sent.
19
21
res : Response ,
20
22
/// The state of the encoding process
@@ -38,7 +40,7 @@ pub(crate) struct Encoder {
38
40
#[ derive( Debug ) ]
39
41
enum State {
40
42
/// Starting state.
41
- Init ,
43
+ Start ,
42
44
/// Write the HEAD section to an intermediate buffer.
43
45
ComputeHead ,
44
46
/// Stream out the HEAD section.
@@ -51,12 +53,26 @@ enum State {
51
53
End ,
52
54
}
53
55
56
+ impl Read for Encoder {
57
+ fn poll_read (
58
+ mut self : Pin < & mut Self > ,
59
+ cx : & mut Context < ' _ > ,
60
+ buf : & mut [ u8 ] ,
61
+ ) -> Poll < io:: Result < usize > > {
62
+ self . bytes_written = 0 ;
63
+ let res = self . exec ( cx, buf) ;
64
+ log:: trace!( "ServerEncoder {} bytes written" , self . bytes_written) ;
65
+ res
66
+ }
67
+ }
68
+
54
69
impl Encoder {
55
70
/// Create a new instance of Encoder.
56
71
pub ( crate ) fn new ( res : Response ) -> Self {
57
72
Self {
58
73
res,
59
- state : State :: Init ,
74
+ depth : 0 ,
75
+ state : State :: Start ,
60
76
bytes_written : 0 ,
61
77
head : vec ! [ ] ,
62
78
head_bytes_written : 0 ,
@@ -66,46 +82,40 @@ impl Encoder {
66
82
}
67
83
}
68
84
69
- pub ( crate ) fn encode (
85
+ /// Switch the internal state to a new state.
86
+ fn set_state (
70
87
& mut self ,
88
+ state : State ,
71
89
cx : & mut Context < ' _ > ,
72
90
buf : & mut [ u8 ] ,
73
91
) -> Poll < io:: Result < usize > > {
74
- self . bytes_written = 0 ;
75
- let res = match self . state {
76
- State :: Init => self . init ( cx, buf) ,
77
- State :: ComputeHead => self . compute_head ( cx, buf) ,
78
- State :: EncodeHead => self . encode_head ( cx, buf) ,
79
- State :: EncodeFixedBody => self . encode_fixed_body ( cx, buf) ,
80
- State :: EncodeChunkedBody => self . encode_chunked_body ( cx, buf) ,
81
- State :: End => Poll :: Ready ( Ok ( self . bytes_written ) ) ,
82
- } ;
83
- log:: trace!( "ServerEncoder {} bytes written" , self . bytes_written) ;
84
- res
85
- }
86
-
87
- /// Switch the internal state to a new state.
88
- fn set_state ( & mut self , state : State ) {
89
92
use State :: * ;
90
- log:: trace!( "Server Encoder state: {:?} -> {:?}" , self . state, state) ;
93
+ log:: trace!( "ServerEncoder state: {:?} -> {:?}" , self . state, state) ;
91
94
92
95
#[ cfg( debug_assertions) ]
93
96
match self . state {
94
- Init => assert ! ( matches!( state, ComputeHead ) ) ,
97
+ Start => assert ! ( matches!( state, ComputeHead ) ) ,
95
98
ComputeHead => assert ! ( matches!( state, EncodeHead ) ) ,
96
99
EncodeHead => assert ! ( matches!( state, EncodeChunkedBody | EncodeFixedBody ) ) ,
97
100
EncodeFixedBody => assert ! ( matches!( state, End ) ) ,
98
101
EncodeChunkedBody => assert ! ( matches!( state, End ) ) ,
99
- End => panic ! ( "No state transitions allowed after the stream has ended" ) ,
102
+ End => panic ! ( "No state transitions allowed after the ServerEncoder has ended" ) ,
100
103
}
101
104
102
105
self . state = state;
106
+ self . exec ( cx, buf)
103
107
}
104
108
105
- /// Initialize to the first state.
106
- fn init ( & mut self , cx : & mut Context < ' _ > , buf : & mut [ u8 ] ) -> Poll < io:: Result < usize > > {
107
- self . set_state ( State :: ComputeHead ) ;
108
- self . compute_head ( cx, buf)
109
+ /// Execute the right method for the current state.
110
+ fn exec ( & mut self , cx : & mut Context < ' _ > , buf : & mut [ u8 ] ) -> Poll < io:: Result < usize > > {
111
+ match self . state {
112
+ State :: Start => self . set_state ( State :: ComputeHead , cx, buf) ,
113
+ State :: ComputeHead => self . compute_head ( cx, buf) ,
114
+ State :: EncodeHead => self . encode_head ( cx, buf) ,
115
+ State :: EncodeFixedBody => self . encode_fixed_body ( cx, buf) ,
116
+ State :: EncodeChunkedBody => self . encode_chunked_body ( cx, buf) ,
117
+ State :: End => Poll :: Ready ( Ok ( self . bytes_written ) ) ,
118
+ }
109
119
}
110
120
111
121
/// Encode the headers to a buffer, the first time we poll.
@@ -142,8 +152,7 @@ impl Encoder {
142
152
143
153
std:: io:: Write :: write_fmt ( & mut self . head , format_args ! ( "\r \n " ) ) ?;
144
154
145
- self . set_state ( State :: EncodeHead ) ;
146
- self . encode_head ( cx, buf)
155
+ self . set_state ( State :: EncodeHead , cx, buf)
147
156
}
148
157
149
158
/// Encode the status code + headers.
@@ -164,18 +173,14 @@ impl Encoder {
164
173
match self . res . len ( ) {
165
174
Some ( body_len) => {
166
175
self . body_len = body_len;
167
- self . state = State :: EncodeFixedBody ;
168
- return self . encode_fixed_body ( cx, buf) ;
176
+ self . set_state ( State :: EncodeFixedBody , cx, buf)
169
177
}
170
- None => {
171
- self . state = State :: EncodeChunkedBody ;
172
- return self . encode_chunked_body ( cx, buf) ;
173
- }
174
- } ;
178
+ None => self . set_state ( State :: EncodeChunkedBody , cx, buf) ,
179
+ }
175
180
} else {
176
181
// If we haven't read the entire header it means `buf` isn't
177
182
// big enough. Break out of loop and return from `poll_read`
178
- return Poll :: Ready ( Ok ( self . bytes_written ) ) ;
183
+ Poll :: Ready ( Ok ( self . bytes_written ) )
179
184
}
180
185
}
181
186
@@ -222,14 +227,13 @@ impl Encoder {
222
227
223
228
if self . body_len == self . body_bytes_written {
224
229
// If we've read the `len` number of bytes, end
225
- self . set_state ( State :: End ) ;
226
- return Poll :: Ready ( Ok ( self . bytes_written ) ) ;
230
+ self . set_state ( State :: End , cx, buf)
227
231
} else if new_body_bytes_written == 0 {
228
232
// If we've reached unexpected EOF, end anyway
229
233
// TODO: do something?
230
- self . set_state ( State :: End ) ;
231
- return Poll :: Ready ( Ok ( self . bytes_written ) ) ;
234
+ self . set_state ( State :: End , cx, buf)
232
235
} else {
236
+ // Else continue encoding
233
237
self . encode_fixed_body ( cx, buf)
234
238
}
235
239
}
@@ -245,28 +249,16 @@ impl Encoder {
245
249
match self . chunked . encode ( & mut self . res , cx, buf) {
246
250
Poll :: Ready ( Ok ( read) ) => {
247
251
self . bytes_written += read;
248
- if self . bytes_written == 0 {
249
- self . set_state ( State :: End ) ;
252
+ match self . bytes_written {
253
+ 0 => self . set_state ( State :: End , cx, buf) ,
254
+ _ => Poll :: Ready ( Ok ( self . bytes_written ) ) ,
250
255
}
251
- Poll :: Ready ( Ok ( self . bytes_written ) )
252
256
}
253
257
Poll :: Ready ( Err ( err) ) => Poll :: Ready ( Err ( err) ) ,
254
- Poll :: Pending => {
255
- if self . bytes_written > 0 {
256
- return Poll :: Ready ( Ok ( self . bytes_written ) ) ;
257
- }
258
- Poll :: Pending
259
- }
258
+ Poll :: Pending => match self . bytes_written {
259
+ 0 => Poll :: Pending ,
260
+ _ => Poll :: Ready ( Ok ( self . bytes_written ) ) ,
261
+ } ,
260
262
}
261
263
}
262
264
}
263
-
264
- impl Read for Encoder {
265
- fn poll_read (
266
- mut self : Pin < & mut Self > ,
267
- cx : & mut Context < ' _ > ,
268
- buf : & mut [ u8 ] ,
269
- ) -> Poll < io:: Result < usize > > {
270
- self . encode ( cx, buf)
271
- }
272
- }
0 commit comments