1 use std::fmt;
2 
3 use bytes::{Buf, IntoBuf};
4 use bytes::buf::{Chain, Take};
5 use iovec::IoVec;
6 
7 use common::StaticBuf;
8 use super::io::WriteBuf;
9 
10 /// Encoders to handle different Transfer-Encodings.
11 #[derive(Debug, Clone, PartialEq)]
12 pub struct Encoder {
13     kind: Kind,
14     is_last: bool,
15 }
16 
17 #[derive(Debug)]
18 pub struct EncodedBuf<B> {
19     kind: BufKind<B>,
20 }
21 
22 #[derive(Debug)]
23 pub struct NotEof;
24 
25 #[derive(Debug, PartialEq, Clone)]
26 enum Kind {
27     /// An Encoder for when Transfer-Encoding includes `chunked`.
28     Chunked,
29     /// An Encoder for when Content-Length is set.
30     ///
31     /// Enforces that the body is not longer than the Content-Length header.
32     Length(u64),
33     /// An Encoder for when neither Content-Length nore Chunked encoding is set.
34     ///
35     /// This is mostly only used with HTTP/1.0 with a length. This kind requires
36     /// the connection to be closed when the body is finished.
37     CloseDelimited,
38 }
39 
40 #[derive(Debug)]
41 enum BufKind<B> {
42     Exact(B),
43     Limited(Take<B>),
44     Chunked(Chain<Chain<ChunkSize, B>, StaticBuf>),
45     ChunkedEnd(StaticBuf),
46 }
47 
48 impl Encoder {
new(kind: Kind) -> Encoder49     fn new(kind: Kind) -> Encoder {
50         Encoder {
51             kind: kind,
52             is_last: false,
53         }
54     }
chunked() -> Encoder55     pub fn chunked() -> Encoder {
56         Encoder::new(Kind::Chunked)
57     }
58 
length(len: u64) -> Encoder59     pub fn length(len: u64) -> Encoder {
60         Encoder::new(Kind::Length(len))
61     }
62 
close_delimited() -> Encoder63     pub fn close_delimited() -> Encoder {
64         Encoder::new(Kind::CloseDelimited)
65     }
66 
is_eof(&self) -> bool67     pub fn is_eof(&self) -> bool {
68         match self.kind {
69             Kind::Length(0) => true,
70             _ => false
71         }
72     }
73 
set_last(mut self, is_last: bool) -> Self74     pub fn set_last(mut self, is_last: bool) -> Self {
75         self.is_last = is_last;
76         self
77     }
78 
is_last(&self) -> bool79     pub fn is_last(&self) -> bool {
80         self.is_last
81     }
82 
end<B>(&self) -> Result<Option<EncodedBuf<B>>, NotEof>83     pub fn end<B>(&self) -> Result<Option<EncodedBuf<B>>, NotEof> {
84         match self.kind {
85             Kind::Length(0) => Ok(None),
86             Kind::Chunked => Ok(Some(EncodedBuf {
87                 kind: BufKind::ChunkedEnd(StaticBuf(b"0\r\n\r\n")),
88             })),
89             _ => Err(NotEof),
90         }
91     }
92 
encode<B>(&mut self, msg: B) -> EncodedBuf<B::Buf> where B: IntoBuf,93     pub fn encode<B>(&mut self, msg: B) -> EncodedBuf<B::Buf>
94     where
95         B: IntoBuf,
96     {
97         let msg = msg.into_buf();
98         let len = msg.remaining();
99         debug_assert!(len > 0, "encode() called with empty buf");
100 
101         let kind = match self.kind {
102             Kind::Chunked => {
103                 trace!("encoding chunked {}B", len);
104                 let buf = ChunkSize::new(len)
105                     .chain(msg)
106                     .chain(StaticBuf(b"\r\n"));
107                 BufKind::Chunked(buf)
108             },
109             Kind::Length(ref mut remaining) => {
110                 trace!("sized write, len = {}", len);
111                 if len as u64 > *remaining {
112                     let limit = *remaining as usize;
113                     *remaining = 0;
114                     BufKind::Limited(msg.take(limit))
115                 } else {
116                     *remaining -= len as u64;
117                     BufKind::Exact(msg)
118                 }
119             },
120             Kind::CloseDelimited => {
121                 trace!("close delimited write {}B", len);
122                 BufKind::Exact(msg)
123             }
124         };
125         EncodedBuf {
126             kind,
127         }
128     }
129 
encode_and_end<B>(&self, msg: B, dst: &mut WriteBuf<EncodedBuf<B::Buf>>) -> bool where B: IntoBuf,130     pub(super) fn encode_and_end<B>(&self, msg: B, dst: &mut WriteBuf<EncodedBuf<B::Buf>>) -> bool
131     where
132         B: IntoBuf,
133     {
134         let msg = msg.into_buf();
135         let len = msg.remaining();
136         debug_assert!(len > 0, "encode() called with empty buf");
137 
138         match self.kind {
139             Kind::Chunked => {
140                 trace!("encoding chunked {}B", len);
141                 let buf = ChunkSize::new(len)
142                     .chain(msg)
143                     .chain(StaticBuf(b"\r\n0\r\n\r\n"));
144                 dst.buffer(buf);
145                 !self.is_last
146             },
147             Kind::Length(remaining) => {
148                 use std::cmp::Ordering;
149 
150                 trace!("sized write, len = {}", len);
151                 match (len as u64).cmp(&remaining) {
152                     Ordering::Equal => {
153                         dst.buffer(msg);
154                         !self.is_last
155                     },
156                     Ordering::Greater => {
157                         dst.buffer(msg.take(remaining as usize));
158                         !self.is_last
159                     },
160                     Ordering::Less => {
161                         dst.buffer(msg);
162                         false
163                     }
164                 }
165             },
166             Kind::CloseDelimited => {
167                 trace!("close delimited write {}B", len);
168                 dst.buffer(msg);
169                 false
170             }
171         }
172     }
173 
174     /// Encodes the full body, without verifying the remaining length matches.
175     ///
176     /// This is used in conjunction with Payload::__hyper_full_data(), which
177     /// means we can trust that the buf has the correct size (the buf itself
178     /// was checked to make the headers).
danger_full_buf<B>(self, msg: B, dst: &mut WriteBuf<EncodedBuf<B::Buf>>) where B: IntoBuf,179     pub(super) fn danger_full_buf<B>(self, msg: B, dst: &mut WriteBuf<EncodedBuf<B::Buf>>)
180     where
181         B: IntoBuf,
182     {
183         let msg = msg.into_buf();
184         debug_assert!(msg.remaining() > 0, "encode() called with empty buf");
185         debug_assert!(match self.kind {
186             Kind::Length(len) => len == msg.remaining() as u64,
187             _ => true,
188         }, "danger_full_buf length mismatches");
189 
190         match self.kind {
191             Kind::Chunked => {
192                 let len = msg.remaining();
193                 trace!("encoding chunked {}B", len);
194                 let buf = ChunkSize::new(len)
195                     .chain(msg)
196                     .chain(StaticBuf(b"\r\n0\r\n\r\n"));
197                 dst.buffer(buf);
198             },
199             _ => {
200                 dst.buffer(msg);
201             },
202         }
203     }
204 }
205 
206 impl<B> Buf for EncodedBuf<B>
207 where
208     B: Buf,
209 {
210     #[inline]
remaining(&self) -> usize211     fn remaining(&self) -> usize {
212         match self.kind {
213             BufKind::Exact(ref b) => b.remaining(),
214             BufKind::Limited(ref b) => b.remaining(),
215             BufKind::Chunked(ref b) => b.remaining(),
216             BufKind::ChunkedEnd(ref b) => b.remaining(),
217         }
218     }
219 
220     #[inline]
bytes(&self) -> &[u8]221     fn bytes(&self) -> &[u8] {
222         match self.kind {
223             BufKind::Exact(ref b) => b.bytes(),
224             BufKind::Limited(ref b) => b.bytes(),
225             BufKind::Chunked(ref b) => b.bytes(),
226             BufKind::ChunkedEnd(ref b) => b.bytes(),
227         }
228     }
229 
230     #[inline]
advance(&mut self, cnt: usize)231     fn advance(&mut self, cnt: usize) {
232         match self.kind {
233             BufKind::Exact(ref mut b) => b.advance(cnt),
234             BufKind::Limited(ref mut b) => b.advance(cnt),
235             BufKind::Chunked(ref mut b) => b.advance(cnt),
236             BufKind::ChunkedEnd(ref mut b) => b.advance(cnt),
237         }
238     }
239 
240     #[inline]
bytes_vec<'t>(&'t self, dst: &mut [&'t IoVec]) -> usize241     fn bytes_vec<'t>(&'t self, dst: &mut [&'t IoVec]) -> usize {
242         match self.kind {
243             BufKind::Exact(ref b) => b.bytes_vec(dst),
244             BufKind::Limited(ref b) => b.bytes_vec(dst),
245             BufKind::Chunked(ref b) => b.bytes_vec(dst),
246             BufKind::ChunkedEnd(ref b) => b.bytes_vec(dst),
247         }
248     }
249 }
250 
251 
252 #[cfg(target_pointer_width = "32")]
253 const USIZE_BYTES: usize = 4;
254 
255 #[cfg(target_pointer_width = "64")]
256 const USIZE_BYTES: usize = 8;
257 
258 // each byte will become 2 hex
259 const CHUNK_SIZE_MAX_BYTES: usize = USIZE_BYTES * 2;
260 
261 #[derive(Clone, Copy)]
262 struct ChunkSize {
263     bytes: [u8; CHUNK_SIZE_MAX_BYTES + 2],
264     pos: u8,
265     len: u8,
266 }
267 
268 impl ChunkSize {
new(len: usize) -> ChunkSize269     fn new(len: usize) -> ChunkSize {
270         use std::fmt::Write;
271         let mut size = ChunkSize {
272             bytes: [0; CHUNK_SIZE_MAX_BYTES + 2],
273             pos: 0,
274             len: 0,
275         };
276         write!(&mut size, "{:X}\r\n", len)
277             .expect("CHUNK_SIZE_MAX_BYTES should fit any usize");
278         size
279     }
280 }
281 
282 impl Buf for ChunkSize {
283     #[inline]
remaining(&self) -> usize284     fn remaining(&self) -> usize {
285         (self.len - self.pos).into()
286     }
287 
288     #[inline]
bytes(&self) -> &[u8]289     fn bytes(&self) -> &[u8] {
290         &self.bytes[self.pos.into() .. self.len.into()]
291     }
292 
293     #[inline]
advance(&mut self, cnt: usize)294     fn advance(&mut self, cnt: usize) {
295         assert!(cnt <= self.remaining());
296         self.pos += cnt as u8; // just asserted cnt fits in u8
297     }
298 }
299 
300 impl fmt::Debug for ChunkSize {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result301     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
302         f.debug_struct("ChunkSize")
303             .field("bytes", &&self.bytes[..self.len.into()])
304             .field("pos", &self.pos)
305             .finish()
306     }
307 }
308 
309 impl fmt::Write for ChunkSize {
write_str(&mut self, num: &str) -> fmt::Result310     fn write_str(&mut self, num: &str) -> fmt::Result {
311         use std::io::Write;
312         (&mut self.bytes[self.len.into()..]).write(num.as_bytes())
313             .expect("&mut [u8].write() cannot error");
314         self.len += num.len() as u8; // safe because bytes is never bigger than 256
315         Ok(())
316     }
317 }
318 
319 impl<B: Buf> From<B> for EncodedBuf<B> {
from(buf: B) -> Self320     fn from(buf: B) -> Self {
321         EncodedBuf {
322             kind: BufKind::Exact(buf),
323         }
324     }
325 }
326 
327 impl<B: Buf> From<Take<B>> for EncodedBuf<B> {
from(buf: Take<B>) -> Self328     fn from(buf: Take<B>) -> Self {
329         EncodedBuf {
330             kind: BufKind::Limited(buf),
331         }
332     }
333 }
334 
335 impl<B: Buf> From<Chain<Chain<ChunkSize, B>, StaticBuf>> for EncodedBuf<B> {
from(buf: Chain<Chain<ChunkSize, B>, StaticBuf>) -> Self336     fn from(buf: Chain<Chain<ChunkSize, B>, StaticBuf>) -> Self {
337         EncodedBuf {
338             kind: BufKind::Chunked(buf),
339         }
340     }
341 }
342 
343 #[cfg(test)]
344 mod tests {
345     use bytes::{BufMut};
346 
347     use super::super::io::Cursor;
348     use super::Encoder;
349 
350     #[test]
chunked()351     fn chunked() {
352         let mut encoder = Encoder::chunked();
353         let mut dst = Vec::new();
354 
355         let msg1 = b"foo bar".as_ref();
356         let buf1 = encoder.encode(msg1);
357         dst.put(buf1);
358         assert_eq!(dst, b"7\r\nfoo bar\r\n");
359 
360         let msg2 = b"baz quux herp".as_ref();
361         let buf2 = encoder.encode(msg2);
362         dst.put(buf2);
363 
364         assert_eq!(dst, b"7\r\nfoo bar\r\nD\r\nbaz quux herp\r\n");
365 
366         let end = encoder.end::<Cursor<Vec<u8>>>().unwrap().unwrap();
367         dst.put(end);
368 
369         assert_eq!(dst, b"7\r\nfoo bar\r\nD\r\nbaz quux herp\r\n0\r\n\r\n".as_ref());
370     }
371 
372     #[test]
length()373     fn length() {
374         let max_len = 8;
375         let mut encoder = Encoder::length(max_len as u64);
376         let mut dst = Vec::new();
377 
378 
379         let msg1 = b"foo bar".as_ref();
380         let buf1 = encoder.encode(msg1);
381         dst.put(buf1);
382 
383 
384         assert_eq!(dst, b"foo bar");
385         assert!(!encoder.is_eof());
386         encoder.end::<()>().unwrap_err();
387 
388         let msg2 = b"baz".as_ref();
389         let buf2 = encoder.encode(msg2);
390         dst.put(buf2);
391 
392         assert_eq!(dst.len(), max_len);
393         assert_eq!(dst, b"foo barb");
394         assert!(encoder.is_eof());
395         assert!(encoder.end::<()>().unwrap().is_none());
396     }
397 
398     #[test]
eof()399     fn eof() {
400         let mut encoder = Encoder::close_delimited();
401         let mut dst = Vec::new();
402 
403 
404         let msg1 = b"foo bar".as_ref();
405         let buf1 = encoder.encode(msg1);
406         dst.put(buf1);
407 
408 
409         assert_eq!(dst, b"foo bar");
410         assert!(!encoder.is_eof());
411         encoder.end::<()>().unwrap_err();
412 
413         let msg2 = b"baz".as_ref();
414         let buf2 = encoder.encode(msg2);
415         dst.put(buf2);
416 
417         assert_eq!(dst, b"foo barbaz");
418         assert!(!encoder.is_eof());
419         encoder.end::<()>().unwrap_err();
420     }
421 }
422