1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 //! HTTP/1 request encoder implementation.
15 //!
16 //! The encoder is used to serialize the request into the specified buf in
17 //! a certain format.
18 //!
19 //! # Examples
20 //!
21 //! ```
22 //! use ylong_http::h1::RequestEncoder;
23 //! use ylong_http::request::Request;
24 //!
25 //! let request = Request::builder()
26 //!     .method("GET")
27 //!     .url("www.example.com")
28 //!     .version("HTTP/1.1")
29 //!     .header("ACCEPT", "text/html")
30 //!     .body(())
31 //!     .unwrap();
32 //!
33 //! // Gets `RequestPart`.
34 //! let (part, _) = request.into_parts();
35 //! let mut encoder = RequestEncoder::new(part);
36 //! encoder.absolute_uri(true);
37 //!
38 //! // We use `message` to store all the body data.
39 //! let mut message = Vec::new();
40 //! // We use `buf` to store save temporary data.
41 //! let mut buf = [0u8; 20];
42 //!
43 //! // First encoding, buf is filled.
44 //! let size = encoder.encode(&mut buf).unwrap();
45 //! assert_eq!(&buf[..size], "GET www.example.com ".as_bytes());
46 //! message.extend_from_slice(&buf[..size]);
47 //!
48 //! // Second encoding, buf is filled.
49 //! let size = encoder.encode(&mut buf).unwrap();
50 //! assert_eq!(&buf[..size], "HTTP/1.1\r\naccept:tex".as_bytes());
51 //! message.extend_from_slice(&buf[..size]);
52 //!
53 //! // Third encoding, part of buf is filled, this indicates that encoding has ended.
54 //! let size = encoder.encode(&mut buf).unwrap();
55 //! assert_eq!(&buf[..size], "t/html\r\n\r\n".as_bytes());
56 //! message.extend_from_slice(&buf[..size]);
57 //!
58 //! // We can assemble temporary data into a complete data.
59 //! let result = "GET www.example.com HTTP/1.1\r\naccept:text/html\r\n\r\n";
60 //! assert_eq!(message.as_slice(), result.as_bytes());
61 //! ```
62 
63 use std::io::Read;
64 
65 use crate::error::{ErrorKind, HttpError};
66 use crate::headers::{HeaderName, Headers, HeadersIntoIter};
67 use crate::request::method::Method;
68 use crate::request::uri::Uri;
69 use crate::request::RequestPart;
70 use crate::version::Version;
71 
72 /// A encoder that is used to encode request message in `HTTP/1` format.
73 ///
74 /// This encoder supports you to use the encode method multiple times to output
75 /// the result in multiple bytes slices.
76 ///
77 /// # Examples
78 ///
79 /// ```
80 /// use ylong_http::h1::RequestEncoder;
81 /// use ylong_http::request::Request;
82 ///
83 /// let request = Request::builder()
84 ///     .method("GET")
85 ///     .url("www.example.com")
86 ///     .version("HTTP/1.1")
87 ///     .header("ACCEPT", "text/html")
88 ///     .body(())
89 ///     .unwrap();
90 ///
91 /// // Gets `RequestPart`.
92 /// let (part, _) = request.into_parts();
93 /// let mut encoder = RequestEncoder::new(part);
94 /// encoder.absolute_uri(true);
95 ///
96 /// // We use `message` to store all the body data.
97 /// let mut message = Vec::new();
98 /// // We use `buf` to store save temporary data.
99 /// let mut buf = [0u8; 20];
100 ///
101 /// // First encoding, buf is filled.
102 /// let size = encoder.encode(&mut buf).unwrap();
103 /// assert_eq!(&buf[..size], "GET www.example.com ".as_bytes());
104 /// message.extend_from_slice(&buf[..size]);
105 ///
106 /// // Second encoding, buf is filled.
107 /// let size = encoder.encode(&mut buf).unwrap();
108 /// assert_eq!(&buf[..size], "HTTP/1.1\r\naccept:tex".as_bytes());
109 /// message.extend_from_slice(&buf[..size]);
110 ///
111 /// // Third encoding, part of buf is filled, this indicates that encoding has ended.
112 /// let size = encoder.encode(&mut buf).unwrap();
113 /// assert_eq!(&buf[..size], "t/html\r\n\r\n".as_bytes());
114 /// message.extend_from_slice(&buf[..size]);
115 ///
116 /// // We can assemble temporary data into a complete data.
117 /// let result = "GET www.example.com HTTP/1.1\r\naccept:text/html\r\n\r\n";
118 /// assert_eq!(message.as_slice(), result.as_bytes());
119 /// ```
120 pub struct RequestEncoder {
121     encode_status: EncodeState,
122     method_part: EncodeMethod,
123     method_sp_part: EncodeSp,
124     uri_part: EncodeUri,
125     uri_sp_part: EncodeSp,
126     version_part: EncodeVersion,
127     version_crlf_part: EncodeCrlf,
128     headers_part: EncodeHeader,
129     headers_crlf_part: EncodeCrlf,
130     is_absolute_uri: bool,
131 }
132 
133 enum EncodeState {
134     // "Method" phase of encoding request-message.
135     Method,
136     // "MethodSp" phase of encoding whitespace after method.
137     MethodSp,
138     // "Uri" phase of encoding request-message.
139     Uri,
140     // "UriSp" phase of encoding whitespace after uri.
141     UriSp,
142     // "Version" phase of encoding request-message.
143     Version,
144     // "VersionCrlf" phase of encoding whitespace after version.
145     VersionCrlf,
146     // "Header" phase of encoding request-message.
147     Header,
148     // "HeaderCrlf" phase of encoding /r/n after header.
149     HeaderCrlf,
150     // "EncodeFinished" phase of finishing the encoding.
151     EncodeFinished,
152 }
153 
154 // Component encoding status.
155 enum TokenStatus<T, E> {
156     // The current component is completely encoded.
157     Complete(T),
158     // The current component is partially encoded.
159     Partial(E),
160 }
161 
162 type TokenResult<T> = Result<TokenStatus<usize, T>, HttpError>;
163 
164 impl RequestEncoder {
165     /// Creates a new `RequestEncoder` from a `RequestPart`.
166     ///
167     /// # Examples
168     ///
169     /// ```
170     /// use ylong_http::h1::RequestEncoder;
171     /// use ylong_http::request::Request;
172     ///
173     /// let request = Request::builder()
174     ///     .method("GET")
175     ///     .url("www.example.com")
176     ///     .version("HTTP/1.1")
177     ///     .header("ACCEPT", "text/html")
178     ///     .body(())
179     ///     .unwrap();
180     ///
181     /// let (part, _) = request.into_parts();
182     /// let encoder = RequestEncoder::new(part);
183     /// ```
new(part: RequestPart) -> Self184     pub fn new(part: RequestPart) -> Self {
185         Self {
186             encode_status: EncodeState::Method,
187             method_part: EncodeMethod::new(part.method),
188             method_sp_part: EncodeSp::new(),
189             uri_part: EncodeUri::new(part.uri, false),
190             uri_sp_part: EncodeSp::new(),
191             version_part: EncodeVersion::new(part.version),
192             version_crlf_part: EncodeCrlf::new(),
193             headers_part: EncodeHeader::new(part.headers),
194             headers_crlf_part: EncodeCrlf::new(),
195             is_absolute_uri: false,
196         }
197     }
198 
199     /// Encodes `RequestPart` into target buf and returns the number of
200     /// bytes written.
201     ///
202     /// If the length of buf is not enough to write all the output results,
203     /// the state will be saved until the next call to this method.
204     ///
205     /// # Return Value
206     ///
207     /// This method may return the following results:
208     ///
209     /// - `Ok(size) && size == buf.len()`: it means that buf has been completely
210     /// filled, but the result may not be fully output. You **must** call this
211     /// method again to obtain the rest part of the result. Otherwise you may
212     /// lose some parts of the result.
213     ///
214     /// - `Ok(size) && size < buf.len()`: it indicates that the result has been
215     /// fully output.
216     ///
217     /// - `Err(e)`: it indicates that an error has occurred during encoding.
218     ///
219     /// # Examples
220     ///
221     /// ```
222     /// use ylong_http::h1::RequestEncoder;
223     /// use ylong_http::request::Request;
224     ///
225     /// let request = Request::builder()
226     ///     .method("GET")
227     ///     .url("www.example.com")
228     ///     .version("HTTP/1.1")
229     ///     .header("ACCEPT", "text/html")
230     ///     .body(())
231     ///     .unwrap();
232     ///
233     /// let (part, _) = request.into_parts();
234     /// let mut encoder = RequestEncoder::new(part);
235     /// encoder.absolute_uri(true);
236     ///
237     /// let mut buf = [0_u8; 10];
238     /// let mut message = Vec::new();
239     /// let mut idx = 0;
240     /// loop {
241     ///     let size = encoder.encode(&mut buf).unwrap();
242     ///     message.extend_from_slice(&buf[..size]);
243     ///     if size < buf.len() {
244     ///         break;
245     ///     }
246     /// }
247     ///
248     /// let result = "GET www.example.com HTTP/1.1\r\naccept:text/html\r\n\r\n";
249     /// assert_eq!(message.as_slice(), result.as_bytes());
250     /// ```
encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>251     pub fn encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
252         if dst.is_empty() {
253             return Err(ErrorKind::InvalidInput.into());
254         }
255         let mut count = 0;
256         while count != dst.len() {
257             count += match self.encode_status {
258                 EncodeState::Method => self.method_encode(&mut dst[count..]),
259                 EncodeState::MethodSp => self.method_sp_encode(&mut dst[count..]),
260                 EncodeState::Uri => self.uri_encode(&mut dst[count..]),
261                 EncodeState::UriSp => self.uri_sp_encode(&mut dst[count..]),
262                 EncodeState::Version => self.version_encode(&mut dst[count..]),
263                 EncodeState::VersionCrlf => self.version_crlf_encode(&mut dst[count..]),
264                 EncodeState::Header => self.header_encode(&mut dst[count..]),
265                 EncodeState::HeaderCrlf => self.header_crlf_encode(&mut dst[count..]),
266                 EncodeState::EncodeFinished => return Ok(count),
267             }?;
268         }
269         Ok(dst.len())
270     }
271 
272     /// Sets the `is_absolute_uri` flag.
273     ///
274     /// If you enable the flag, the uri part will be encoded as absolute form
275     /// in the headline. Otherwise the uri part will be encoded as origin form.
276     ///
277     /// You should use this method before the uri part being encoded.
278     ///
279     /// # Examples
280     ///
281     /// ```
282     /// use ylong_http::h1::RequestEncoder;
283     /// use ylong_http::request::Request;
284     ///
285     /// let request = Request::builder()
286     ///     .method("GET")
287     ///     .url("www.example.com")
288     ///     .version("HTTP/1.1")
289     ///     .header("ACCEPT", "text/html")
290     ///     .body(())
291     ///     .unwrap();
292     ///
293     /// let (part, _) = request.into_parts();
294     /// let mut encoder = RequestEncoder::new(part);
295     /// // After you create the request encoder, users can choose to set the uri form.
296     /// encoder.absolute_uri(false);
297     ///
298     /// let mut buf = [0u8; 1024];
299     /// let size = encoder.encode(&mut buf).unwrap();
300     /// // If you disable the `is_absolute_uri` flag, the uri will be encoded as a origin form.
301     /// assert_eq!(
302     ///     &buf[..size],
303     ///     b"GET / HTTP/1.1\r\naccept:text/html\r\n\r\n".as_slice()
304     /// );
305     /// ```
absolute_uri(&mut self, is_absolute: bool)306     pub fn absolute_uri(&mut self, is_absolute: bool) {
307         self.is_absolute_uri = is_absolute;
308     }
309 
method_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>310     fn method_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
311         match self.method_part.encode(dst)? {
312             TokenStatus::Complete(output_size) => {
313                 self.encode_status = EncodeState::MethodSp;
314                 Ok(output_size)
315             }
316             TokenStatus::Partial(output_size) => {
317                 self.encode_status = EncodeState::Method;
318                 Ok(output_size)
319             }
320         }
321     }
322 
method_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>323     fn method_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
324         match self.method_sp_part.encode(dst)? {
325             TokenStatus::Complete(output_size) => {
326                 self.uri_part.is_absolute = self.is_absolute_uri;
327                 self.encode_status = EncodeState::Uri;
328                 Ok(output_size)
329             }
330             TokenStatus::Partial(output_size) => {
331                 self.encode_status = EncodeState::MethodSp;
332                 Ok(output_size)
333             }
334         }
335     }
336 
uri_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>337     fn uri_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
338         match self.uri_part.encode(dst)? {
339             TokenStatus::Complete(output_size) => {
340                 self.encode_status = EncodeState::UriSp;
341                 Ok(output_size)
342             }
343             TokenStatus::Partial(output_size) => {
344                 self.encode_status = EncodeState::Uri;
345                 Ok(output_size)
346             }
347         }
348     }
349 
uri_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>350     fn uri_sp_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
351         match self.uri_sp_part.encode(dst)? {
352             TokenStatus::Complete(output_size) => {
353                 self.encode_status = EncodeState::Version;
354                 Ok(output_size)
355             }
356             TokenStatus::Partial(output_size) => {
357                 self.encode_status = EncodeState::UriSp;
358                 Ok(output_size)
359             }
360         }
361     }
362 
version_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>363     fn version_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
364         match self.version_part.encode(dst)? {
365             TokenStatus::Complete(output_size) => {
366                 self.encode_status = EncodeState::VersionCrlf;
367                 Ok(output_size)
368             }
369             TokenStatus::Partial(output_size) => {
370                 self.encode_status = EncodeState::Version;
371                 Ok(output_size)
372             }
373         }
374     }
375 
version_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>376     fn version_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
377         match self.version_crlf_part.encode(dst)? {
378             TokenStatus::Complete(output_size) => {
379                 self.encode_status = EncodeState::Header;
380                 Ok(output_size)
381             }
382             TokenStatus::Partial(output_size) => {
383                 self.encode_status = EncodeState::VersionCrlf;
384                 Ok(output_size)
385             }
386         }
387     }
388 
header_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>389     fn header_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
390         match self.headers_part.encode(dst)? {
391             TokenStatus::Complete(output_size) => {
392                 self.encode_status = EncodeState::HeaderCrlf;
393                 Ok(output_size)
394             }
395             TokenStatus::Partial(output_size) => {
396                 self.encode_status = EncodeState::Header;
397                 Ok(output_size)
398             }
399         }
400     }
401 
header_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError>402     fn header_crlf_encode(&mut self, dst: &mut [u8]) -> Result<usize, HttpError> {
403         match self.headers_crlf_part.encode(dst)? {
404             TokenStatus::Complete(output_size) => {
405                 self.encode_status = EncodeState::EncodeFinished;
406                 Ok(output_size)
407             }
408             TokenStatus::Partial(output_size) => {
409                 self.encode_status = EncodeState::HeaderCrlf;
410                 Ok(output_size)
411             }
412         }
413     }
414 }
415 
416 struct EncodeMethod {
417     inner: Method,
418     src_idx: usize,
419 }
420 
421 impl EncodeMethod {
new(method: Method) -> Self422     fn new(method: Method) -> Self {
423         Self {
424             inner: method,
425             src_idx: 0,
426         }
427     }
428 
encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>429     fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
430         let method = self.inner.as_str().as_bytes();
431         WriteData::new(method, &mut self.src_idx, buf).write()
432     }
433 }
434 
435 struct EncodeUri {
436     absolute: Vec<u8>,
437     origin: Vec<u8>,
438     src_idx: usize,
439     is_absolute: bool,
440 }
441 
442 impl EncodeUri {
new(uri: Uri, is_absolute: bool) -> Self443     fn new(uri: Uri, is_absolute: bool) -> Self {
444         let mut origin_form = vec![];
445         let path = uri.path_and_query();
446         if let Some(p) = path {
447             origin_form = p.as_bytes().to_vec();
448         } else {
449             origin_form.extend_from_slice(b"/");
450         }
451         let init_uri = uri.to_string().into_bytes();
452         Self {
453             absolute: init_uri,
454             origin: origin_form,
455             src_idx: 0,
456             is_absolute,
457         }
458     }
459 
encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>460     fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
461         let mut uri = self.origin.as_slice();
462         if self.is_absolute {
463             uri = self.absolute.as_slice();
464         }
465         WriteData::new(uri, &mut self.src_idx, buf).write()
466     }
467 }
468 
469 struct EncodeVersion {
470     inner: Version,
471     src_idx: usize,
472 }
473 
474 impl EncodeVersion {
new(version: Version) -> Self475     fn new(version: Version) -> Self {
476         Self {
477             inner: version,
478             src_idx: 0,
479         }
480     }
481 
encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>482     fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
483         let version = self.inner.as_str().as_bytes();
484         let mut task = WriteData::new(version, &mut self.src_idx, buf);
485         task.write()
486     }
487 }
488 
489 struct EncodeHeader {
490     inner: HeadersIntoIter,
491     status: Option<HeaderStatus>,
492     name: HeaderName,
493     value: Vec<u8>,
494     name_idx: usize,
495     colon_idx: usize,
496     value_idx: usize,
497 }
498 
499 enum HeaderStatus {
500     Name,
501     Colon,
502     Value,
503     Crlf(EncodeCrlf),
504     EmptyHeader,
505 }
506 
507 impl EncodeHeader {
new(header: Headers) -> Self508     fn new(header: Headers) -> Self {
509         let mut header_iter = header.into_iter();
510         if let Some((header_name, header_value)) = header_iter.next() {
511             Self {
512                 inner: header_iter,
513                 status: Some(HeaderStatus::Name),
514                 name: header_name,
515                 value: header_value.to_string().unwrap().into_bytes(),
516                 name_idx: 0,
517                 colon_idx: 0,
518                 value_idx: 0,
519             }
520         } else {
521             Self {
522                 inner: header_iter,
523                 status: Some(HeaderStatus::EmptyHeader),
524                 name: HeaderName::from_bytes(" ".as_bytes()).unwrap(),
525                 value: vec![],
526                 name_idx: 0,
527                 colon_idx: 0,
528                 value_idx: 0,
529             }
530         }
531     }
532 
encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>533     fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
534         match self.status.take().unwrap() {
535             HeaderStatus::Name => self.encode_name(buf),
536             HeaderStatus::Colon => self.encode_colon(buf),
537             HeaderStatus::Value => self.encode_value(buf),
538             HeaderStatus::Crlf(crlf) => self.encode_crlf(buf, crlf),
539             HeaderStatus::EmptyHeader => Ok(TokenStatus::Complete(0)),
540         }
541     }
542 
encode_name(&mut self, buf: &mut [u8]) -> TokenResult<usize>543     fn encode_name(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
544         let name = self.name.as_bytes();
545         let mut task = WriteData::new(name, &mut self.name_idx, buf);
546         match task.write()? {
547             TokenStatus::Complete(size) => {
548                 self.status = Some(HeaderStatus::Colon);
549                 Ok(TokenStatus::Partial(size))
550             }
551             TokenStatus::Partial(size) => {
552                 self.status = Some(HeaderStatus::Name);
553                 Ok(TokenStatus::Partial(size))
554             }
555         }
556     }
557 
encode_colon(&mut self, buf: &mut [u8]) -> TokenResult<usize>558     fn encode_colon(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
559         let colon = ":".as_bytes();
560         let mut task = WriteData::new(colon, &mut self.colon_idx, buf);
561         match task.write()? {
562             TokenStatus::Complete(size) => {
563                 self.status = Some(HeaderStatus::Value);
564                 Ok(TokenStatus::Partial(size))
565             }
566             TokenStatus::Partial(size) => {
567                 self.status = Some(HeaderStatus::Colon);
568                 Ok(TokenStatus::Partial(size))
569             }
570         }
571     }
572 
encode_value(&mut self, buf: &mut [u8]) -> TokenResult<usize>573     fn encode_value(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
574         let value = self.value.as_slice();
575         let mut task = WriteData::new(value, &mut self.value_idx, buf);
576         match task.write()? {
577             TokenStatus::Complete(size) => {
578                 let crlf = EncodeCrlf::new();
579                 self.status = Some(HeaderStatus::Crlf(crlf));
580                 Ok(TokenStatus::Partial(size))
581             }
582             TokenStatus::Partial(size) => {
583                 self.status = Some(HeaderStatus::Value);
584                 Ok(TokenStatus::Partial(size))
585             }
586         }
587     }
588 
encode_crlf(&mut self, buf: &mut [u8], mut crlf: EncodeCrlf) -> TokenResult<usize>589     fn encode_crlf(&mut self, buf: &mut [u8], mut crlf: EncodeCrlf) -> TokenResult<usize> {
590         match crlf.encode(buf)? {
591             TokenStatus::Complete(size) => {
592                 if let Some(iter) = self.inner.next() {
593                     let (header_name, header_value) = iter;
594                     self.status = Some(HeaderStatus::Name);
595                     self.name = header_name;
596                     self.value = header_value.to_string().unwrap().into_bytes();
597                     self.name_idx = 0;
598                     self.colon_idx = 0;
599                     self.value_idx = 0;
600                     Ok(TokenStatus::Partial(size))
601                 } else {
602                     Ok(TokenStatus::Complete(size))
603                 }
604             }
605             TokenStatus::Partial(size) => {
606                 self.status = Some(HeaderStatus::Crlf(crlf));
607                 Ok(TokenStatus::Partial(size))
608             }
609         }
610     }
611 }
612 
613 struct EncodeSp {
614     src_idx: usize,
615 }
616 
617 impl EncodeSp {
new() -> Self618     fn new() -> Self {
619         Self { src_idx: 0 }
620     }
621 
encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>622     fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
623         let sp = " ".as_bytes();
624         let mut task = WriteData::new(sp, &mut self.src_idx, buf);
625         task.write()
626     }
627 }
628 
629 struct EncodeCrlf {
630     src_idx: usize,
631 }
632 
633 impl EncodeCrlf {
new() -> Self634     fn new() -> Self {
635         Self { src_idx: 0 }
636     }
637 
encode(&mut self, buf: &mut [u8]) -> TokenResult<usize>638     fn encode(&mut self, buf: &mut [u8]) -> TokenResult<usize> {
639         let crlf = "\r\n".as_bytes();
640         let mut task = WriteData::new(crlf, &mut self.src_idx, buf);
641         task.write()
642     }
643 }
644 
645 struct WriteData<'a> {
646     src: &'a [u8],
647     src_idx: &'a mut usize,
648     dst: &'a mut [u8],
649 }
650 
651 impl<'a> WriteData<'a> {
new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self652     fn new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self {
653         WriteData { src, src_idx, dst }
654     }
655 
write(&mut self) -> TokenResult<usize>656     fn write(&mut self) -> TokenResult<usize> {
657         let src_idx = *self.src_idx;
658         let input_len = self.src.len() - src_idx;
659         let output_len = self.dst.len();
660         let num = (&self.src[src_idx..]).read(self.dst).unwrap();
661         if output_len >= input_len {
662             return Ok(TokenStatus::Complete(num));
663         }
664         *self.src_idx += num;
665         Ok(TokenStatus::Partial(num))
666     }
667 }
668 impl Default for RequestEncoder {
default() -> Self669     fn default() -> Self {
670         RequestEncoder::new(RequestPart::default())
671     }
672 }
673 
674 #[cfg(test)]
675 mod ut_request_encoder {
676     use super::RequestEncoder;
677     use crate::request::{Request, RequestBuilder};
678 
679     /// UT test cases for `RequestEncoder::new`.
680     ///
681     /// # Brief
682     /// 1. Calls `RequestEncoder::new` to create a `RequestEncoder`.
683     #[test]
ut_request_encoder_new()684     fn ut_request_encoder_new() {
685         let request = Request::new(());
686         let (part, _) = request.into_parts();
687         let _encoder = RequestEncoder::new(part);
688         // Success if no panic.
689     }
690 
691     /// UT test cases for `RequestEncoder::encode`.
692     ///
693     /// # Brief
694     /// 1. Creates a `Request` by calling methods of `Request::builder`.
695     /// 2. Gets a request part by calling `Request::into_parts`.
696     /// 3. Creates a `RequestEncoder` by calling `RequestBuilder::new`.
697     /// 4. Calls `RequestEncoder::encode` method in a loop and collects the
698     ///    results.
699     /// 5. Checks if the test result is correct.
700     #[test]
ut_request_encoder_encode_1()701     fn ut_request_encoder_encode_1() {
702         macro_rules! encoder_test_case {
703             (
704                 Method: $method:expr,
705                 Uri: $uri:expr,
706                 Version: $version:expr,
707                 $(Header: $name:expr, $value:expr,)*
708                 RequestLine: $request_line:expr,
709             ) => {{
710                 let request = Request::builder()
711                     .method($method)
712                     .url($uri)
713                     .version($version)
714                     $(.header($name, $value))*
715                     .body(())
716                     .unwrap();
717 
718                 let (part, _) = request.into_parts();
719                 let mut encoder = RequestEncoder::new(part);
720                 encoder.absolute_uri(true);
721                 let mut buf = [0u8; 5];
722                 let mut res = Vec::new();
723                 loop {
724                     let size = encoder.encode(&mut buf).unwrap();
725                     res.extend_from_slice(&buf[..size]);
726                     if size < buf.len() {
727                         break;
728                     }
729                 }
730 
731                 let str = std::str::from_utf8(res.as_slice())
732                     .expect("Cannot convert res to &str");
733 
734                 assert!(str.find($request_line).is_some());
735 
736                 $(
737                     let target_header = format!(
738                         "{}:{}\r\n",
739                         ($name).to_lowercase(),
740                         ($value).to_lowercase(),
741                     );
742                     assert!(str.find(target_header.as_str()).is_some());
743                 )*
744             }};
745         }
746 
747         // No header-lines.
748         encoder_test_case! {
749             Method: "GET",
750             Uri: "www.example.com",
751             Version: "HTTP/1.1",
752             RequestLine: "GET www.example.com HTTP/1.1\r\n",
753         }
754 
755         // 1 header-line.
756         encoder_test_case! {
757             Method: "GET",
758             Uri: "www.example.com",
759             Version: "HTTP/1.1",
760             Header: "ACCEPT", "text/html",
761             RequestLine: "GET www.example.com HTTP/1.1\r\n",
762         }
763 
764         // More than 1 header-lines.
765         encoder_test_case! {
766             Method: "GET",
767             Uri: "www.example.com",
768             Version: "HTTP/1.1",
769             Header: "ACCEPT", "text/html",
770             Header: "HOST", "127.0.0.1",
771             RequestLine: "GET www.example.com HTTP/1.1\r\n",
772         }
773     }
774 
775     /// UT test cases for `RequestEncoder::absolute_uri`.
776     ///
777     /// # Brief
778     /// 1. Creates a `Request` by calling `RequestBuilder::build`.
779     /// 2. Calls absolute_uri.
780     /// 3. Checks if the test result is correct.
781     #[test]
ut_request_encoder_set_proxy()782     fn ut_request_encoder_set_proxy() {
783         let request = RequestBuilder::new()
784             .method("GET")
785             .url("www.example.com")
786             .version("HTTP/1.1")
787             .body(())
788             .unwrap();
789         let (part, _) = request.into_parts();
790         let mut encoder = RequestEncoder::new(part);
791         assert!(!encoder.is_absolute_uri);
792 
793         encoder.absolute_uri(true);
794         assert!(encoder.is_absolute_uri);
795         encoder.absolute_uri(false);
796 
797         let mut buf = [0u8; 100];
798         let size = encoder.encode(&mut buf).unwrap();
799         let res = std::str::from_utf8(&buf[..size]).unwrap();
800         assert_eq!(res, "GET / HTTP/1.1\r\n\r\n");
801     }
802 }
803