1use bytes::BufMut;
6
7use super::*;
8
9pub struct Builder<B> {
11 buf: B,
12 framing: Framing,
13}
14
15impl<B: BufMut> Builder<B> {
16 pub fn new(buf: B, framing: Framing) -> Self {
18 Self { buf, framing }
19 }
20
21 pub fn push_ctrl(
23 mut self,
24 mut method: &[u8],
25 mut scheme: &[u8],
26 mut authority: &[u8],
27 mut path: &[u8],
28 ) -> Result<HeaderBuilder<B>> {
29 if !self.framing.is_request() {
30 return Err(Error::UnexpectedFraming);
31 }
32
33 if !self.buf.has_remaining_mut() {
34 return Err(Error::ShortBuf);
35 }
36 self.buf.put_u8(self.framing as u8);
37
38 compose_len_bytes(&mut self.buf, &mut method)?;
39 compose_len_bytes(&mut self.buf, &mut scheme)?;
40 compose_len_bytes(&mut self.buf, &mut authority)?;
41 compose_len_bytes(&mut self.buf, &mut path)?;
42
43 Ok(HeaderBuilder {
44 buf: self.buf,
45 framing: self.framing,
46 appending: false,
47 })
48 }
49
50 pub fn push_status(mut self, status: usize) -> Result<InfoBuilder<B>> {
52 if self.framing.is_request() {
53 return Err(Error::UnexpectedFraming);
54 }
55
56 if !self.buf.has_remaining_mut() {
57 return Err(Error::ShortBuf);
58 }
59 self.buf.put_u8(self.framing as u8);
60
61 VarInt::try_from(status)?.compose(&mut self.buf)?;
62
63 Ok(InfoBuilder {
64 buf: self.buf,
65 framing: self.framing,
66 is_final: is_final_ctrl(status),
67 appending: false,
68 })
69 }
70}
71
72pub struct RCtrlBuilder<B> {
74 buf: B,
75 framing: Framing,
76}
77
78impl<B: BufMut> RCtrlBuilder<B> {
79 pub fn push_status(mut self, status: usize) -> Result<InfoBuilder<B>> {
81 VarInt::try_from(status)?.compose(&mut self.buf)?;
82 Ok(InfoBuilder {
83 buf: self.buf,
84 framing: self.framing,
85 is_final: is_final_ctrl(status),
86 appending: false,
87 })
88 }
89}
90
91pub struct InfoBuilder<B> {
93 buf: B,
94 framing: Framing,
95 is_final: bool,
96 appending: bool,
97}
98
99impl<B: BufMut> InfoBuilder<B> {
100 pub fn push_fields(mut self, fields: &[(&[u8], &[u8])]) -> Result<RCtrlBuilder<B>> {
102 if self.is_final {
103 return Err(Error::UnexpectedBuildState);
104 }
105
106 push_fields(&mut self.buf, self.framing, fields)?;
107 Ok(RCtrlBuilder {
108 buf: self.buf,
109 framing: self.framing,
110 })
111 }
112
113 pub fn append_field(mut self, field: (&[u8], &[u8])) -> Result<Self> {
115 if self.framing.known_len() {
116 return Err(Error::UnexpectedFraming);
117 }
118
119 if self.is_final {
120 return Err(Error::UnexpectedBuildState);
121 }
122
123 let (mut name, mut value) = field;
124 if name.is_empty() {
125 return Err(Error::InvalidInput);
126 }
127 compose_len_bytes(&mut self.buf, &mut name)?;
128 compose_len_bytes(&mut self.buf, &mut value)?;
129 self.appending = true;
130 Ok(self)
131 }
132
133 pub fn done(mut self) -> Result<RCtrlBuilder<B>> {
135 if self.framing.known_len() {
136 return Err(Error::UnexpectedFraming);
137 }
138
139 if self.is_final || !self.appending {
140 return Err(Error::UnexpectedBuildState);
141 }
142
143 if !self.buf.has_remaining_mut() {
144 return Err(Error::ShortBuf);
145 }
146 self.buf.put_u8(CONTENT_TERMINATOR);
147
148 Ok(RCtrlBuilder {
149 buf: self.buf,
150 framing: self.framing,
151 })
152 }
153
154 pub fn next(self) -> Result<HeaderBuilder<B>> {
156 if !self.is_final {
157 return Err(Error::UnexpectedBuildState);
158 }
159
160 Ok(HeaderBuilder {
161 buf: self.buf,
162 framing: self.framing,
163 appending: false,
164 })
165 }
166}
167
168pub struct HeaderBuilder<B> {
170 buf: B,
171 framing: Framing,
172 appending: bool,
173}
174
175impl<B: BufMut> HeaderBuilder<B> {
176 pub fn push_headers(mut self, fields: &[(&[u8], &[u8])]) -> Result<ContentBuilder<B>> {
178 push_fields(&mut self.buf, self.framing, fields)?;
179 Ok(ContentBuilder {
180 buf: self.buf,
181 framing: self.framing,
182 appending: false,
183 })
184 }
185
186 pub fn append_header(mut self, field: (&[u8], &[u8])) -> Result<Self> {
188 if self.framing.known_len() {
189 return Err(Error::UnexpectedFraming);
190 }
191
192 let (mut name, mut value) = field;
193 if name.is_empty() {
194 return Err(Error::InvalidInput);
195 }
196 compose_len_bytes(&mut self.buf, &mut name)?;
197 compose_len_bytes(&mut self.buf, &mut value)?;
198 self.appending = true;
199 Ok(self)
200 }
201
202 pub fn next(mut self) -> Result<ContentBuilder<B>> {
204 if !self.appending {
205 return Err(Error::UnexpectedBuildState);
206 }
207
208 if !self.buf.has_remaining_mut() {
209 return Err(Error::ShortBuf);
210 }
211 self.buf.put_u8(CONTENT_TERMINATOR);
212 Ok(ContentBuilder {
213 buf: self.buf,
214 framing: self.framing,
215 appending: false,
216 })
217 }
218}
219
220pub struct ContentBuilder<B> {
222 buf: B,
223 framing: Framing,
224 appending: bool,
225}
226
227impl<B: BufMut> ContentBuilder<B> {
228 pub fn push_content(mut self, mut content: &[u8]) -> Result<TailerBuilder<B>> {
230 let empty = content.is_empty();
231 compose_len_bytes(&mut self.buf, &mut content)?;
232
233 if !self.framing.known_len() && !empty {
235 if !self.buf.has_remaining_mut() {
236 return Err(Error::ShortBuf);
237 }
238 self.buf.put_u8(CONTENT_TERMINATOR);
239 }
240
241 Ok(TailerBuilder {
242 buf: self.buf,
243 framing: self.framing,
244 appending: false,
245 })
246 }
247
248 pub fn append_chunk(mut self, mut chunk: &[u8]) -> Result<Self> {
250 if chunk.is_empty() {
251 return Err(Error::InvalidInput);
252 }
253
254 compose_len_bytes(&mut self.buf, &mut chunk)?;
255 self.appending = true;
256 Ok(self)
257 }
258
259 pub fn next(mut self) -> Result<TailerBuilder<B>> {
261 if !self.buf.has_remaining_mut() {
262 return Err(Error::ShortBuf);
263 }
264 self.buf.put_u8(CONTENT_TERMINATOR);
265
266 Ok(TailerBuilder {
267 buf: self.buf,
268 framing: self.framing,
269 appending: false,
270 })
271 }
272}
273
274pub struct TailerBuilder<B> {
276 buf: B,
277 framing: Framing,
278 appending: bool,
279}
280
281impl<B: BufMut> TailerBuilder<B> {
282 pub fn push_tailers(mut self, fields: &[(&[u8], &[u8])]) -> Result<PaddingBuilder<B>> {
284 push_fields(&mut self.buf, self.framing, fields)?;
285 Ok(PaddingBuilder { buf: self.buf })
286 }
287
288 pub fn append_tailer(mut self, field: (&[u8], &[u8])) -> Result<Self> {
290 if self.framing.known_len() {
291 return Err(Error::UnexpectedFraming);
292 }
293
294 let (mut name, mut value) = field;
295 if name.is_empty() {
296 return Err(Error::InvalidInput);
297 }
298 compose_len_bytes(&mut self.buf, &mut name)?;
299 compose_len_bytes(&mut self.buf, &mut value)?;
300 self.appending = true;
301 Ok(self)
302 }
303
304 pub fn next(mut self) -> Result<PaddingBuilder<B>> {
306 if !self.appending {
307 return Err(Error::UnexpectedBuildState);
308 }
309
310 if !self.buf.has_remaining_mut() {
311 return Err(Error::ShortBuf);
312 }
313 self.buf.put_u8(CONTENT_TERMINATOR);
314 Ok(PaddingBuilder { buf: self.buf })
315 }
316}
317
318pub struct PaddingBuilder<B> {
320 buf: B,
321}
322
323impl<B: BufMut> PaddingBuilder<B> {
324 pub fn push_padding(mut self, n: usize) -> Result<()> {
326 if self.buf.remaining_mut() < n {
327 return Err(Error::ShortBuf);
328 }
329 self.buf.put_bytes(CONTENT_TERMINATOR, n);
330 Ok(())
331 }
332}
333
334fn push_fields<B: BufMut>(buf: &mut B, framing: Framing, fields: &[(&[u8], &[u8])]) -> Result<()> {
335 if framing.known_len() {
336 push_fields_with_len(buf, fields)
337 } else {
338 push_fields_no_len(buf, fields)
339 }
340}
341
342fn push_fields_with_len<B: BufMut>(buf: &mut B, fields: &[(&[u8], &[u8])]) -> Result<()> {
343 let mut len = 0;
344 for (name, value) in fields.iter() {
345 len += VarInt::try_from(name.len())?.size();
346 len += name.len();
347 len += VarInt::try_from(value.len())?.size();
348 len += value.len();
349 }
350
351 let n = VarInt::try_from(len)?;
352 if buf.remaining_mut() < n.size() + len {
353 return Err(Error::ShortBuf);
354 }
355
356 n.compose(buf)?;
357
358 for (mut name, mut value) in fields.iter() {
359 compose_len_bytes(buf, &mut name)?;
360 compose_len_bytes(buf, &mut value)?;
361 }
362
363 Ok(())
364}
365
366fn push_fields_no_len<B: BufMut>(buf: &mut B, fields: &[(&[u8], &[u8])]) -> Result<()> {
367 for (mut name, mut value) in fields.iter() {
368 if name.is_empty() {
369 return Err(Error::InvalidInput);
370 }
371 compose_len_bytes(buf, &mut name)?;
372 compose_len_bytes(buf, &mut value)?;
373 }
374
375 if !buf.has_remaining_mut() {
376 return Err(Error::ShortBuf);
377 }
378 buf.put_u8(CONTENT_TERMINATOR);
379
380 Ok(())
381}
382
383fn compose_len_bytes<B: BufMut, T: Buf>(buf: &mut B, data: &mut T) -> Result<()> {
385 let len = data.remaining();
386 let n = VarInt::try_from(len)?;
387
388 if buf.remaining_mut() < n.size() + len {
389 return Err(Error::ShortBuf);
390 }
391
392 n.compose(buf)?;
393 buf.put(data);
394 Ok(())
395}
396
397#[cfg(test)]
398mod tests {
399 use super::super::tests::*;
400 use super::*;
401
402 #[test]
403 fn build_known_len_req() {
404 let mut buf = Vec::new();
405 Builder::new(&mut buf, Framing::KnownLenReq)
406 .push_ctrl(b"GET", b"https", b"", b"/hello.txt")
407 .unwrap()
408 .push_headers(&[
409 (
410 &b"user-agent"[..],
411 &b"curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3"[..],
412 ),
413 (&b"host"[..], &b"www.example.com"[..]),
414 (&b"accept-language"[..], &b"en, mi"[..]),
415 ])
416 .unwrap()
417 .push_content(&[])
418 .unwrap()
419 .push_tailers(&[])
420 .unwrap();
421 assert_eq!(EXAMPLE_KNOWN_LEN_REQ2, buf);
422 }
423
424 #[test]
425 fn build_ind_len_req() {
426 let mut buf = Vec::new();
427 Builder::new(&mut buf, Framing::IndLenReq)
428 .push_ctrl(b"GET", b"https", b"", b"/hello.txt")
429 .unwrap()
430 .push_headers(&[
431 (
432 &b"user-agent"[..],
433 &b"curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3"[..],
434 ),
435 (&b"host"[..], &b"www.example.com"[..]),
436 (&b"accept-language"[..], &b"en, mi"[..]),
437 ])
438 .unwrap()
439 .push_content(&[])
440 .unwrap()
441 .push_tailers(&[])
442 .unwrap()
443 .push_padding(10)
444 .unwrap();
445 assert_eq!(EXAMPLE_IND_LEN_REQ1, buf);
446 }
447
448 #[test]
449 fn build_known_len_res() {
450 let mut buf = Vec::new();
451 Builder::new(&mut buf, Framing::KnownLenRes)
452 .push_status(200)
453 .unwrap()
454 .next()
455 .unwrap()
456 .push_headers(&[])
457 .unwrap()
458 .push_content("This content contains CRLF.\r\n".as_bytes())
459 .unwrap()
460 .push_tailers(&[("trailer".as_bytes(), "text".as_bytes())])
461 .unwrap();
462 assert_eq!(EXAMPLE_KNOWN_LEN_RES1, buf);
463 }
464
465 #[test]
466 fn build_ind_len_res() {
467 let mut buf = Vec::new();
468 Builder::new(&mut buf, Framing::IndLenRes)
469 .push_status(102)
470 .unwrap()
471 .push_fields(&[("running".as_bytes(), r#""sleep 15""#.as_bytes())])
472 .unwrap()
473 .push_status(103)
474 .unwrap()
475 .push_fields(&[
476 (
477 "link".as_bytes(),
478 r#"</style.css>; rel=preload; as=style"#.as_bytes(),
479 ),
480 (
481 "link".as_bytes(),
482 r#"</script.js>; rel=preload; as=script"#.as_bytes(),
483 ),
484 ])
485 .unwrap()
486 .push_status(200)
487 .unwrap()
488 .next()
489 .unwrap()
490 .push_headers(&[
491 (
492 "date".as_bytes(),
493 r#"Mon, 27 Jul 2009 12:28:53 GMT"#.as_bytes(),
494 ),
495 ("server".as_bytes(), "Apache".as_bytes()),
496 (
497 "last-modified".as_bytes(),
498 "Wed, 22 Jul 2009 19:15:56 GMT".as_bytes(),
499 ),
500 ("etag".as_bytes(), r#""34aa387-d-1568eb00""#.as_bytes()),
501 ("accept-ranges".as_bytes(), "bytes".as_bytes()),
502 ("content-length".as_bytes(), "51".as_bytes()),
503 ("vary".as_bytes(), "Accept-Encoding".as_bytes()),
504 ("content-type".as_bytes(), "text/plain".as_bytes()),
505 ])
506 .unwrap()
507 .push_content("Hello World! My content includes a trailing CRLF.\r\n".as_bytes())
508 .unwrap()
509 .push_tailers(&[])
510 .unwrap();
511
512 assert_eq!(EXAMPLE_IND_LEN_RES1, &buf);
513 }
514}