Skip to content

Commit db1c1d7

Browse files
committed
server encoder docs and fewer allocations
1 parent 9f3a100 commit db1c1d7

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

src/server/encode.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,25 @@ impl Encoder {
196196
}
197197
}
198198

199+
/// Encode an AsyncBufRead using "chunked" framing. This is used for streams
200+
/// whose length is not known up front.
201+
///
202+
/// # Format
203+
///
204+
/// Each "chunk" uses the following encoding:
205+
///
206+
/// ```txt
207+
/// 1. {byte length of `data` as hex}\r\n
208+
/// 2. {data}\r\n
209+
/// ```
210+
///
211+
/// A chunk stream is finalized by appending the following:
212+
///
213+
/// ```txt
214+
/// 1. 0\r\n
215+
/// 2. {trailing header}\r\n (can be repeated)
216+
/// 3. \r\n
217+
/// ```
199218
fn encode_chunked_body(
200219
&mut self,
201220
cx: &mut Context<'_>,
@@ -230,13 +249,15 @@ impl Encoder {
230249
return Poll::Ready(Ok(self.bytes_read));
231250
}
232251

233-
// Each chunk is prefixed with the length, then a CRLF, then the
234-
// content, then another CRLF. Ensure we leave enough space in the
235-
// buffer to read all that.
252+
// Each chunk is prefixed with the length of the data in hex, then a
253+
// CRLF, then the content, then another CRLF. Calculate how many bytes
254+
// each part should be.
236255
let buf_len = buf.len().checked_sub(self.bytes_read).unwrap_or(0);
237256
let amt = src.len().min(buf_len);
238-
let len_prefix = format!("{:X}", amt).into_bytes();
239-
let buf_upper = buf_len.checked_sub(len_prefix.len() + 4).unwrap_or(0);
257+
// Calculate the max char count encoding the `len_prefix` statement
258+
// as hex would take. This is done by rounding up `log16(amt)`.
259+
let hex_len = (amt as f64).log(16.0).ceil() as usize;
260+
let buf_upper = buf_len.checked_sub(hex_len + 4).unwrap_or(0);
240261
let amt = amt.min(buf_upper);
241262
let len_prefix = format!("{:X}", amt).into_bytes();
242263

0 commit comments

Comments
 (0)