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 use core::cmp::min;
15 use core::pin::Pin;
16 use core::task::{Context, Poll};
17 use std::io::{Error, Read};
18 
19 use super::origin::{FromAsyncReader, FromBytes, FromReader};
20 use super::{async_impl, sync_impl};
21 use crate::body::origin::FromAsyncBody;
22 use crate::{AsyncRead, ReadBuf};
23 
24 /// `TextBody` is used to represent the body of plain text type.
25 ///
26 /// You can create a `TextBody` in a variety of ways, such as reading from
27 /// memory or reading from a file.
28 ///
29 /// # Read From Memory
30 ///
31 /// You can create a `TextBody` by reading memory slice.
32 ///
33 /// For example, you can use a memory slice to create a `TextBody`:
34 ///
35 /// ```
36 /// use ylong_http::body::TextBody;
37 ///
38 /// let text = "Hello World";
39 /// let body = TextBody::from_bytes(text.as_bytes());
40 /// ```
41 ///
42 /// This type of `TextBody` implements both [`sync_impl::Body`] and
43 /// [`async_impl::Body`].
44 ///
45 /// # Read From Reader
46 ///
47 /// You can create a `TextBody` by reading from a synchronous reader.
48 ///
49 /// For example, you can use a `&[u8]` to create a `TextBody`:
50 ///
51 /// ```no_run
52 /// use ylong_http::body::TextBody;
53 ///
54 /// // In this usage `&[u8]` is treated as a synchronous reader.
55 /// let reader = "Hello World";
56 /// let body = TextBody::from_reader(reader.as_bytes());
57 /// ```
58 ///
59 /// This type of `TextBody` **only** implements [`sync_impl::Body`].
60 ///
61 /// # Read From Async Reader
62 ///
63 /// You can create a `TextBody` by reading from an asynchronous reader.
64 ///
65 /// For example, you can use a `&[u8]` to create a `TextBody`:
66 ///
67 /// ```no_run
68 /// use ylong_http::body::TextBody;
69 ///
70 /// async fn text_body_from_async_reader() {
71 ///     // In this usage `&[u8]` is treated as an asynchronous reader.
72 ///     let reader = "Hello World";
73 ///     let body = TextBody::from_async_reader(reader.as_bytes());
74 /// }
75 /// ```
76 ///
77 /// This type of `TextBody` **only** implements [`async_impl::Body`].
78 ///
79 /// # Read Body Content
80 ///
81 /// After you have created a `TextBody`, you can use the methods of
82 /// [`sync_impl::Body`] or [`async_impl::Body`] to read data, like the examples
83 /// below:
84 ///
85 /// sync:
86 ///
87 /// ```no_run
88 /// use ylong_http::body::sync_impl::Body;
89 /// use ylong_http::body::TextBody;
90 ///
91 /// let text = "Hello World";
92 /// let mut body = TextBody::from_bytes(text.as_bytes());
93 ///
94 /// let mut buf = [0u8; 1024];
95 /// loop {
96 ///     let size = body.data(&mut buf).unwrap();
97 ///     if size == 0 {
98 ///         break;
99 ///     }
100 ///     // Operates on the data you read..
101 /// }
102 /// ```
103 ///
104 /// async:
105 ///
106 /// ```no_run
107 /// use ylong_http::body::async_impl::Body;
108 /// use ylong_http::body::TextBody;
109 ///
110 /// async fn read_from_body() {
111 ///     let text = "Hello World";
112 ///     let mut body = TextBody::from_bytes(text.as_bytes());
113 ///
114 ///     let mut buf = [0u8; 1024];
115 ///     loop {
116 ///         let size = body.data(&mut buf).await.unwrap();
117 ///         if size == 0 {
118 ///             break;
119 ///         }
120 ///         // Operates on the data you read..
121 ///     }
122 /// }
123 /// ```
124 ///
125 /// [`sync_impl::Body`]: sync_impl::Body
126 /// [`async_impl::Body`]: async_impl::Body
127 pub struct TextBody<T> {
128     from: T,
129 }
130 
131 impl<'a> TextBody<FromBytes<'a>> {
132     /// Creates a `TextBody` by a memory slice.
133     ///
134     /// # Examples
135     ///
136     /// ```
137     /// use ylong_http::body::TextBody;
138     ///
139     /// let text = "Hello World";
140     /// let body = TextBody::from_bytes(text.as_bytes());
141     /// ```
from_bytes(bytes: &'a [u8]) -> Self142     pub fn from_bytes(bytes: &'a [u8]) -> Self {
143         TextBody {
144             from: FromBytes::new(bytes),
145         }
146     }
147 }
148 
149 impl<T: Read> TextBody<FromReader<T>> {
150     /// Creates a `TextBody` from a synchronous reader.
151     ///
152     /// ```no_run
153     /// use ylong_http::body::TextBody;
154     ///
155     /// // In this usage `&[u8]` is treated as a synchronous reader.
156     /// let reader = "Hello World";
157     /// let body = TextBody::from_reader(reader.as_bytes());
158     /// ```
from_reader(reader: T) -> Self159     pub fn from_reader(reader: T) -> Self {
160         TextBody {
161             from: FromReader::new(reader),
162         }
163     }
164 }
165 
166 impl<T: AsyncRead + Unpin + Send + Sync> TextBody<FromAsyncReader<T>> {
167     /// Creates a `TextBody` from an asynchronous reader.
168     ///
169     /// ```no_run
170     /// use ylong_http::body::TextBody;
171     ///
172     /// async fn text_body_from_async_reader() {
173     ///     let reader = "Hello World";
174     ///     let body = TextBody::from_async_reader(reader.as_bytes());
175     /// }
176     /// ```
from_async_reader(reader: T) -> Self177     pub fn from_async_reader(reader: T) -> Self {
178         Self {
179             from: FromAsyncReader::new(reader),
180         }
181     }
182 }
183 
184 impl<'a> sync_impl::Body for TextBody<FromBytes<'a>> {
185     type Error = Error;
186 
data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>187     fn data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
188         Read::read(&mut *self.from, buf)
189     }
190 }
191 
192 impl<'c> async_impl::Body for TextBody<FromBytes<'c>> {
193     type Error = Error;
194 
poll_data( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>195     fn poll_data(
196         mut self: Pin<&mut Self>,
197         _cx: &mut Context<'_>,
198         buf: &mut [u8],
199     ) -> Poll<Result<usize, Self::Error>> {
200         Poll::Ready(Read::read(&mut *self.from, buf))
201     }
202 }
203 
204 impl<T: Read> sync_impl::Body for TextBody<FromReader<T>> {
205     type Error = Error;
206 
data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>207     fn data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
208         self.from.read(buf)
209     }
210 }
211 
212 impl<T: AsyncRead + Unpin + Send + Sync> async_impl::Body for TextBody<FromAsyncReader<T>> {
213     type Error = Error;
214 
poll_data( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>215     fn poll_data(
216         mut self: Pin<&mut Self>,
217         cx: &mut Context<'_>,
218         buf: &mut [u8],
219     ) -> Poll<Result<usize, Self::Error>> {
220         let mut buf = ReadBuf::new(buf);
221         match Pin::new(&mut *self.from).poll_read(cx, &mut buf) {
222             Poll::Ready(Ok(())) => Poll::Ready(Ok(buf.filled().len())),
223             Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
224             Poll::Pending => Poll::Pending,
225         }
226     }
227 }
228 
229 /// A decoder for decoding plaintext body.
230 ///
231 /// You need to provide the decoder with a body length and some byte slices
232 /// containing a legal body. The decoder will divide the correct body and
233 /// redundant parts according to the `HTTP` syntax.
234 ///
235 /// This decoder supports decoding segmented byte slices.
236 ///
237 /// # Examples
238 ///
239 /// ```
240 /// use ylong_http::body::TextBodyDecoder;
241 ///
242 /// // Creates a decoder and set the body length to 20.
243 /// let mut decoder = TextBodyDecoder::new(20);
244 ///
245 /// // Provides the decoder with the first slice that may contain the body data.
246 /// // The length of this slice is 10, which is less than 20, so it is considered
247 /// // legal body data.
248 /// // The remaining body length is 10 after decoding.
249 /// let slice1 = b"This is a ";
250 /// let (text, left) = decoder.decode(slice1);
251 /// // Since the slice provided before is not enough for the decoder to
252 /// // complete the decoding, the status of the returned `Text` is `Partial`
253 /// // and no left data is returned.
254 /// assert!(text.is_partial());
255 /// assert_eq!(text.data(), b"This is a ");
256 /// assert!(left.is_empty());
257 ///
258 /// // Provides the decoder with the second slice that may contain the body data.
259 /// // The data length is 26, which is more than 10, so the first 10 bytes of
260 /// // the data will be considered legal body, and the rest will be considered
261 /// // redundant data.
262 /// let slice2 = b"text body.[REDUNDANT DATA]";
263 /// let (text, left) = decoder.decode(slice2);
264 /// // Since the body data is fully decoded, the status of the returned `Text`
265 /// // is `Complete`. The left data is also returned.
266 /// assert!(text.is_complete());
267 /// assert_eq!(text.data(), b"text body.");
268 /// assert_eq!(left, b"[REDUNDANT DATA]");
269 ///
270 /// // Provides the decoder with the third slice. Since the body data has been
271 /// // fully decoded, the given slice is regard as redundant data.
272 /// let slice3 = b"[REDUNDANT DATA]";
273 /// let (text, left) = decoder.decode(slice3);
274 /// assert!(text.is_complete());
275 /// assert!(text.data().is_empty());
276 /// assert_eq!(left, b"[REDUNDANT DATA]");
277 /// ```
278 pub struct TextBodyDecoder {
279     left: u64,
280 }
281 
282 impl TextBodyDecoder {
283     /// Creates a new `TextBodyDecoder` from a body length.
284     ///
285     /// This body length generally comes from the `Content-Length` field.
286     ///
287     /// # Examples
288     ///
289     /// ```
290     /// use ylong_http::body::TextBodyDecoder;
291     ///
292     /// let decoder = TextBodyDecoder::new(10);
293     /// ```
new(length: u64) -> TextBodyDecoder294     pub fn new(length: u64) -> TextBodyDecoder {
295         TextBodyDecoder { left: length }
296     }
297 
298     /// Decodes a byte slice that may contain a plaintext body. This method
299     /// supports decoding segmented byte slices.
300     ///
301     /// After each call to this method, a `Text` and a `&[u8]` are returned.
302     /// `Text` contains a piece of legal body data inside. The returned `&[u8]`
303     /// contains redundant data.
304     ///
305     /// # Examples
306     ///
307     /// ```
308     /// use ylong_http::body::TextBodyDecoder;
309     ///
310     /// // Creates a decoder and set the body length to 20.
311     /// let mut decoder = TextBodyDecoder::new(20);
312     ///
313     /// // Provides the decoder with the first slice that may contain the body data.
314     /// // The length of this slice is 10, which is less than 20, so it is considered
315     /// // legal body data.
316     /// // The remaining body length is 10 after decoding.
317     /// let slice1 = b"This is a ";
318     /// let (text, left) = decoder.decode(slice1);
319     /// // Since the slice provided before is not enough for the decoder to
320     /// // complete the decoding, the status of the returned `Text` is `Partial`
321     /// // and no left data is returned.
322     /// assert!(text.is_partial());
323     /// assert_eq!(text.data(), b"This is a ");
324     /// assert!(left.is_empty());
325     ///
326     /// // Provides the decoder with the second slice that may contain the body data.
327     /// // The data length is 26, which is more than 10, so the first 10 bytes of
328     /// // the data will be considered legal body, and the rest will be considered
329     /// // redundant data.
330     /// let slice2 = b"text body.[REDUNDANT DATA]";
331     /// let (text, left) = decoder.decode(slice2);
332     /// // Since the body data is fully decoded, the status of the returned `Text`
333     /// // is `Complete`. The left data is also returned.
334     /// assert!(text.is_complete());
335     /// assert_eq!(text.data(), b"text body.");
336     /// assert_eq!(left, b"[REDUNDANT DATA]");
337     ///
338     /// // Provides the decoder with the third slice. Since the body data has been
339     /// // fully decoded, the given slice is regard as redundant data.
340     /// let slice3 = b"[REDUNDANT DATA]";
341     /// let (text, left) = decoder.decode(slice3);
342     /// assert!(text.is_complete());
343     /// assert!(text.data().is_empty());
344     /// assert_eq!(left, b"[REDUNDANT DATA]");
345     /// ```
decode<'a>(&mut self, buf: &'a [u8]) -> (Text<'a>, &'a [u8])346     pub fn decode<'a>(&mut self, buf: &'a [u8]) -> (Text<'a>, &'a [u8]) {
347         if self.left == 0 {
348             return (Text::complete(&buf[..0]), buf);
349         }
350 
351         let size = min(self.left, buf.len() as u64);
352         self.left -= size;
353         let end = size as usize;
354         if self.left == 0 {
355             (Text::complete(&buf[..end]), &buf[end..])
356         } else {
357             (Text::partial(&buf[..end]), &buf[end..])
358         }
359     }
360 }
361 
362 /// Decode result of a text buffer.
363 /// The `state` records the decode status, and the data records the decoded
364 /// data.
365 #[derive(Debug)]
366 pub struct Text<'a> {
367     state: TextState,
368     data: &'a [u8],
369 }
370 
371 impl<'a> Text<'a> {
372     /// Checks whether this `Text` contains the last valid part of the body
373     /// data.
374     ///
375     /// # Examples
376     ///
377     /// ```
378     /// use ylong_http::body::TextBodyDecoder;
379     ///
380     /// let bytes = b"This is a ";
381     /// let mut decoder = TextBodyDecoder::new(20);
382     /// let (text, _) = decoder.decode(bytes);
383     /// assert!(!text.is_complete());
384     ///
385     /// let bytes = b"text body.";
386     /// let (text, _) = decoder.decode(bytes);
387     /// assert!(text.is_complete());
388     /// ```
is_complete(&self) -> bool389     pub fn is_complete(&self) -> bool {
390         matches!(self.state, TextState::Complete)
391     }
392 
393     /// Checks whether this `Text` contains a non-last part of the body data.
394     ///
395     /// # Examples
396     ///
397     /// ```
398     /// use ylong_http::body::TextBodyDecoder;
399     ///
400     /// let bytes = b"This is a ";
401     /// let mut decoder = TextBodyDecoder::new(20);
402     /// let (text, _) = decoder.decode(bytes);
403     /// assert!(text.is_partial());
404     ///
405     /// let bytes = b"text body.";
406     /// let (text, _) = decoder.decode(bytes);
407     /// assert!(!text.is_partial());
408     /// ```
is_partial(&self) -> bool409     pub fn is_partial(&self) -> bool {
410         !self.is_complete()
411     }
412 
413     /// Gets the underlying data of this `Text`. The returned data is a part
414     /// of the body data.
415     ///
416     /// # Examples
417     ///
418     /// ```
419     /// use ylong_http::body::TextBodyDecoder;
420     ///
421     /// let bytes = b"This is a text body.";
422     /// let mut decoder = TextBodyDecoder::new(20);
423     /// let (text, _) = decoder.decode(bytes);
424     /// assert_eq!(text.data(), b"This is a text body.");
425     /// ```
data(&self) -> &[u8]426     pub fn data(&self) -> &[u8] {
427         self.data
428     }
429 
complete(data: &'a [u8]) -> Self430     pub(crate) fn complete(data: &'a [u8]) -> Self {
431         Self {
432             state: TextState::Complete,
433             data,
434         }
435     }
436 
partial(data: &'a [u8]) -> Self437     pub(crate) fn partial(data: &'a [u8]) -> Self {
438         Self {
439             state: TextState::Partial,
440             data,
441         }
442     }
443 }
444 
445 #[derive(Debug)]
446 enum TextState {
447     Partial,
448     Complete,
449 }
450 
451 #[cfg(test)]
452 mod ut_text {
453     use crate::body::text::{TextBody, TextBodyDecoder};
454 
455     /// UT test cases for `TextBody::from_bytes`.
456     ///
457     /// # Brief
458     /// 1. Calls `TextBody::from_bytes()` to create a `TextBody`.
459     #[test]
ut_text_body_from_bytes()460     fn ut_text_body_from_bytes() {
461         let bytes = b"Hello World!";
462         let _body = TextBody::from_bytes(bytes);
463         // Success if no panic.
464     }
465 
466     /// UT test cases for `TextBody::from_reader`.
467     ///
468     /// # Brief
469     /// 1. Calls `TextBody::from_reader()` to create a `TextBody`.
470     #[test]
ut_text_body_from_reader()471     fn ut_text_body_from_reader() {
472         let reader = "Hello World!".as_bytes();
473         let _body = TextBody::from_reader(reader);
474         // Success if no panic.
475     }
476 
477     /// UT test cases for `TextBody::from_async_reader`.
478     ///
479     /// # Brief
480     /// 1. Calls `TextBody::from_async_reader()` to create a `TextBody`.
481     #[test]
ut_text_body_from_async_reader()482     fn ut_text_body_from_async_reader() {
483         let reader = "Hello World!".as_bytes();
484         let _body = TextBody::from_async_reader(reader);
485         // Success if no panic.
486     }
487 
488     /// UT test cases for `sync_impl::Body::data` of `TextBody<FromBytes<'_>>`.
489     ///
490     /// # Brief
491     /// 1. Creates a `TextBody<FromBytes<'_>>`.
492     /// 2. Calls its `sync_impl::Body::data` method and then checks the results.
493     #[test]
ut_text_body_from_bytes_syn_data()494     fn ut_text_body_from_bytes_syn_data() {
495         use crate::body::sync_impl::Body;
496 
497         let bytes = b"Hello World!";
498         let mut body = TextBody::from_bytes(bytes);
499         let mut buf = [0u8; 5];
500 
501         let size = body.data(&mut buf).expect("First read failed.");
502         assert_eq!(size, 5);
503         assert_eq!(&buf[..size], b"Hello");
504 
505         let size = body.data(&mut buf).expect("Second read failed.");
506         assert_eq!(size, 5);
507         assert_eq!(&buf[..size], b" Worl");
508 
509         let size = body.data(&mut buf).expect("Third read failed.");
510         assert_eq!(size, 2);
511         assert_eq!(&buf[..size], b"d!");
512     }
513 
514     /// UT test cases for `async_impl::Body::data` of `TextBody<FromBytes<'_>>`.
515     ///
516     /// # Brief
517     /// 1. Creates a `TextBody<FromBytes<'_>>`.
518     /// 2. Calls its `async_impl::Body::data` method and then checks the
519     ///    results.
520     #[cfg(feature = "ylong_base")]
521     #[test]
ut_text_body_from_bytes_asyn_data()522     fn ut_text_body_from_bytes_asyn_data() {
523         let handle = ylong_runtime::spawn(async move {
524             text_body_from_bytes_asyn_data().await;
525         });
526         ylong_runtime::block_on(handle).unwrap();
527     }
528 
529     #[cfg(feature = "ylong_base")]
text_body_from_bytes_asyn_data()530     async fn text_body_from_bytes_asyn_data() {
531         use crate::body::async_impl::Body;
532 
533         let bytes = b"Hello World!";
534         let mut body = TextBody::from_bytes(bytes);
535         let mut buf = [0u8; 5];
536 
537         let size = body.data(&mut buf).await.expect("First read failed.");
538         assert_eq!(size, 5);
539         assert_eq!(&buf[..size], b"Hello");
540 
541         let size = body.data(&mut buf).await.expect("Second read failed.");
542         assert_eq!(size, 5);
543         assert_eq!(&buf[..size], b" Worl");
544 
545         let size = body.data(&mut buf).await.expect("Third read failed.");
546         assert_eq!(size, 2);
547         assert_eq!(&buf[..size], b"d!");
548     }
549 
550     /// UT test cases for `sync_impl::Body::data` of `TextBody<FromReader<T>>`.
551     ///
552     /// # Brief
553     /// 1. Creates a `TextBody<FromReader<T>>`.
554     /// 2. Calls its `sync_impl::Body::data` method and then checks the results.
555     #[test]
ut_text_body_from_reader_syn_data()556     fn ut_text_body_from_reader_syn_data() {
557         use crate::body::sync_impl::Body;
558 
559         let reader = "Hello World!".as_bytes();
560         let mut body = TextBody::from_reader(reader);
561         let mut buf = [0u8; 5];
562 
563         let size = body.data(&mut buf).expect("First read failed.");
564         assert_eq!(size, 5);
565         assert_eq!(&buf[..size], b"Hello");
566 
567         let size = body.data(&mut buf).expect("Second read failed.");
568         assert_eq!(size, 5);
569         assert_eq!(&buf[..size], b" Worl");
570 
571         let size = body.data(&mut buf).expect("Third read failed.");
572         assert_eq!(size, 2);
573         assert_eq!(&buf[..size], b"d!");
574     }
575 
576     /// UT test cases for `async_impl::Body::data` of
577     /// `TextBody<FromAsyncReader<T>>`.
578     ///
579     /// # Brief
580     /// 1. Creates a `TextBody<FromAsyncReader<T>>`.
581     /// 2. Calls its `async_impl::Body::data` method and then checks the
582     ///    results.
583     #[cfg(feature = "ylong_base")]
584     #[test]
ut_text_body_from_async_reader_asyn_data()585     fn ut_text_body_from_async_reader_asyn_data() {
586         let handle = ylong_runtime::spawn(async move {
587             text_body_from_async_reader_asyn_data().await;
588         });
589         ylong_runtime::block_on(handle).unwrap();
590     }
591 
592     #[cfg(feature = "ylong_base")]
text_body_from_async_reader_asyn_data()593     async fn text_body_from_async_reader_asyn_data() {
594         use crate::body::async_impl::Body;
595 
596         let reader = "Hello World!".as_bytes();
597         let mut body = TextBody::from_async_reader(reader);
598         let mut buf = [0u8; 5];
599 
600         let size = body.data(&mut buf).await.expect("First read failed.");
601         assert_eq!(size, 5);
602         assert_eq!(&buf[..size], b"Hello");
603 
604         let size = body.data(&mut buf).await.expect("Second read failed.");
605         assert_eq!(size, 5);
606         assert_eq!(&buf[..size], b" Worl");
607 
608         let size = body.data(&mut buf).await.expect("Third read failed.");
609         assert_eq!(size, 2);
610         assert_eq!(&buf[..size], b"d!");
611     }
612 
613     /// UT test cases for `TextBodyDecoder::decode`.
614     ///
615     /// # Brief
616     /// 1. Creates a `TextBodyDecoder` by calling `TextBodyDecoder::new`.
617     /// 2. Decodes text body by calling `TextBodyDecoder::decode`
618     /// 3. Checks if the test result is correct.
619     #[test]
ut_text_body_decoder_decode()620     fn ut_text_body_decoder_decode() {
621         // Test 1:
622         let bytes = b"this is the text body! and this is remaining data";
623         let mut decoder = TextBodyDecoder::new(22);
624         let (text, left) = decoder.decode(&bytes[..4]);
625         assert!(text.is_partial());
626         assert_eq!(text.data(), b"this");
627         assert!(left.is_empty());
628 
629         let (text, left) = decoder.decode(&bytes[4..11]);
630         assert!(text.is_partial());
631         assert_eq!(text.data(), b" is the");
632         assert!(left.is_empty());
633 
634         let (text, left) = decoder.decode(&bytes[11..26]);
635         assert!(text.is_complete());
636         assert_eq!(text.data(), b" text body!");
637         assert_eq!(left, b" and");
638 
639         let (text, left) = decoder.decode(&bytes[26..]);
640         assert!(text.is_complete());
641         assert!(text.data().is_empty());
642         assert_eq!(left, b" this is remaining data");
643 
644         // Test 2:
645         let bytes = b"this is the text body! And this is remaining data";
646         let mut decoder = TextBodyDecoder::new(22);
647         let (text, left) = decoder.decode(bytes);
648         assert!(text.is_complete());
649         assert_eq!(text.data(), b"this is the text body!");
650         assert_eq!(left, b" And this is remaining data");
651     }
652 }
653