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<T: async_impl::Body> TextBody<FromAsyncBody<T>> { 185 /// Creates a `TextBody` from an asynchronous body. 186 /// 187 /// ```no_run 188 /// use ylong_http::body::TextBody; 189 /// 190 /// async fn text_body_from_async_body() { 191 /// let reader = "Hello World"; 192 /// let body = TextBody::from_async_body(reader.as_bytes()); 193 /// } 194 /// ``` from_async_body(body: T) -> Self195 pub fn from_async_body(body: T) -> Self { 196 Self { 197 from: FromAsyncBody::new(body), 198 } 199 } 200 } 201 202 impl<'a> sync_impl::Body for TextBody<FromBytes<'a>> { 203 type Error = Error; 204 data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>205 fn data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { 206 Read::read(&mut *self.from, buf) 207 } 208 } 209 210 impl<'c> async_impl::Body for TextBody<FromBytes<'c>> { 211 type Error = Error; 212 poll_data( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>213 fn poll_data( 214 mut self: Pin<&mut Self>, 215 _cx: &mut Context<'_>, 216 buf: &mut [u8], 217 ) -> Poll<Result<usize, Self::Error>> { 218 Poll::Ready(Read::read(&mut *self.from, buf)) 219 } 220 } 221 222 impl<T: Read> sync_impl::Body for TextBody<FromReader<T>> { 223 type Error = Error; 224 data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>225 fn data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { 226 self.from.read(buf) 227 } 228 } 229 230 impl<T: AsyncRead + Unpin + Send + Sync> async_impl::Body for TextBody<FromAsyncReader<T>> { 231 type Error = Error; 232 poll_data( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>233 fn poll_data( 234 mut self: Pin<&mut Self>, 235 cx: &mut Context<'_>, 236 buf: &mut [u8], 237 ) -> Poll<Result<usize, Self::Error>> { 238 let mut buf = ReadBuf::new(buf); 239 match Pin::new(&mut *self.from).poll_read(cx, &mut buf) { 240 Poll::Ready(Ok(())) => Poll::Ready(Ok(buf.filled().len())), 241 Poll::Ready(Err(e)) => Poll::Ready(Err(e)), 242 Poll::Pending => Poll::Pending, 243 } 244 } 245 } 246 247 impl<T: async_impl::Body> async_impl::Body for TextBody<FromAsyncBody<T>> { 248 type Error = T::Error; 249 poll_data( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>250 fn poll_data( 251 mut self: Pin<&mut Self>, 252 cx: &mut Context<'_>, 253 buf: &mut [u8], 254 ) -> Poll<Result<usize, Self::Error>> { 255 Pin::new(&mut *self.from).poll_data(cx, buf) 256 } 257 } 258 259 /// A decoder for decoding plaintext body. 260 /// 261 /// You need to provide the decoder with a body length and some byte slices 262 /// containing a legal body. The decoder will divide the correct body and 263 /// redundant parts according to the `HTTP` syntax. 264 /// 265 /// This decoder supports decoding segmented byte slices. 266 /// 267 /// # Examples 268 /// 269 /// ``` 270 /// use ylong_http::body::TextBodyDecoder; 271 /// 272 /// // Creates a decoder and set the body length to 20. 273 /// let mut decoder = TextBodyDecoder::new(20); 274 /// 275 /// // Provides the decoder with the first slice that may contain the body data. 276 /// // The length of this slice is 10, which is less than 20, so it is considered 277 /// // legal body data. 278 /// // The remaining body length is 10 after decoding. 279 /// let slice1 = b"This is a "; 280 /// let (text, left) = decoder.decode(slice1); 281 /// // Since the slice provided before is not enough for the decoder to 282 /// // complete the decoding, the status of the returned `Text` is `Partial` 283 /// // and no left data is returned. 284 /// assert!(text.is_partial()); 285 /// assert_eq!(text.data(), b"This is a "); 286 /// assert!(left.is_empty()); 287 /// 288 /// // Provides the decoder with the second slice that may contain the body data. 289 /// // The data length is 26, which is more than 10, so the first 10 bytes of 290 /// // the data will be considered legal body, and the rest will be considered 291 /// // redundant data. 292 /// let slice2 = b"text body.[REDUNDANT DATA]"; 293 /// let (text, left) = decoder.decode(slice2); 294 /// // Since the body data is fully decoded, the status of the returned `Text` 295 /// // is `Complete`. The left data is also returned. 296 /// assert!(text.is_complete()); 297 /// assert_eq!(text.data(), b"text body."); 298 /// assert_eq!(left, b"[REDUNDANT DATA]"); 299 /// 300 /// // Provides the decoder with the third slice. Since the body data has been 301 /// // fully decoded, the given slice is regard as redundant data. 302 /// let slice3 = b"[REDUNDANT DATA]"; 303 /// let (text, left) = decoder.decode(slice3); 304 /// assert!(text.is_complete()); 305 /// assert!(text.data().is_empty()); 306 /// assert_eq!(left, b"[REDUNDANT DATA]"); 307 /// ``` 308 pub struct TextBodyDecoder { 309 left: usize, 310 } 311 312 impl TextBodyDecoder { 313 /// Creates a new `TextBodyDecoder` from a body length. 314 /// 315 /// This body length generally comes from the `Content-Length` field. 316 /// 317 /// # Examples 318 /// 319 /// ``` 320 /// use ylong_http::body::TextBodyDecoder; 321 /// 322 /// let decoder = TextBodyDecoder::new(10); 323 /// ``` new(length: usize) -> TextBodyDecoder324 pub fn new(length: usize) -> TextBodyDecoder { 325 TextBodyDecoder { left: length } 326 } 327 328 /// Decodes a byte slice that may contain a plaintext body. This method 329 /// supports decoding segmented byte slices. 330 /// 331 /// After each call to this method, a `Text` and a `&[u8]` are returned. 332 /// `Text` contains a piece of legal body data inside. The returned `&[u8]` 333 /// contains redundant data. 334 /// 335 /// # Examples 336 /// 337 /// ``` 338 /// use ylong_http::body::TextBodyDecoder; 339 /// 340 /// // Creates a decoder and set the body length to 20. 341 /// let mut decoder = TextBodyDecoder::new(20); 342 /// 343 /// // Provides the decoder with the first slice that may contain the body data. 344 /// // The length of this slice is 10, which is less than 20, so it is considered 345 /// // legal body data. 346 /// // The remaining body length is 10 after decoding. 347 /// let slice1 = b"This is a "; 348 /// let (text, left) = decoder.decode(slice1); 349 /// // Since the slice provided before is not enough for the decoder to 350 /// // complete the decoding, the status of the returned `Text` is `Partial` 351 /// // and no left data is returned. 352 /// assert!(text.is_partial()); 353 /// assert_eq!(text.data(), b"This is a "); 354 /// assert!(left.is_empty()); 355 /// 356 /// // Provides the decoder with the second slice that may contain the body data. 357 /// // The data length is 26, which is more than 10, so the first 10 bytes of 358 /// // the data will be considered legal body, and the rest will be considered 359 /// // redundant data. 360 /// let slice2 = b"text body.[REDUNDANT DATA]"; 361 /// let (text, left) = decoder.decode(slice2); 362 /// // Since the body data is fully decoded, the status of the returned `Text` 363 /// // is `Complete`. The left data is also returned. 364 /// assert!(text.is_complete()); 365 /// assert_eq!(text.data(), b"text body."); 366 /// assert_eq!(left, b"[REDUNDANT DATA]"); 367 /// 368 /// // Provides the decoder with the third slice. Since the body data has been 369 /// // fully decoded, the given slice is regard as redundant data. 370 /// let slice3 = b"[REDUNDANT DATA]"; 371 /// let (text, left) = decoder.decode(slice3); 372 /// assert!(text.is_complete()); 373 /// assert!(text.data().is_empty()); 374 /// assert_eq!(left, b"[REDUNDANT DATA]"); 375 /// ``` decode<'a>(&mut self, buf: &'a [u8]) -> (Text<'a>, &'a [u8])376 pub fn decode<'a>(&mut self, buf: &'a [u8]) -> (Text<'a>, &'a [u8]) { 377 if self.left == 0 { 378 return (Text::complete(&buf[..0]), buf); 379 } 380 381 let size = min(self.left, buf.len()); 382 self.left -= size; 383 if self.left == 0 { 384 (Text::complete(&buf[..size]), &buf[size..]) 385 } else { 386 (Text::partial(&buf[..size]), &buf[size..]) 387 } 388 } 389 } 390 391 /// Decode result of a text buffer. 392 /// The `state` records the decode status, and the data records the decoded 393 /// data. 394 #[derive(Debug)] 395 pub struct Text<'a> { 396 state: TextState, 397 data: &'a [u8], 398 } 399 400 impl<'a> Text<'a> { 401 /// Checks whether this `Text` contains the last valid part of the body 402 /// data. 403 /// 404 /// # Examples 405 /// 406 /// ``` 407 /// use ylong_http::body::TextBodyDecoder; 408 /// 409 /// let bytes = b"This is a "; 410 /// let mut decoder = TextBodyDecoder::new(20); 411 /// let (text, _) = decoder.decode(bytes); 412 /// assert!(!text.is_complete()); 413 /// 414 /// let bytes = b"text body."; 415 /// let (text, _) = decoder.decode(bytes); 416 /// assert!(text.is_complete()); 417 /// ``` is_complete(&self) -> bool418 pub fn is_complete(&self) -> bool { 419 matches!(self.state, TextState::Complete) 420 } 421 422 /// Checks whether this `Text` contains a non-last part of the body data. 423 /// 424 /// # Examples 425 /// 426 /// ``` 427 /// use ylong_http::body::TextBodyDecoder; 428 /// 429 /// let bytes = b"This is a "; 430 /// let mut decoder = TextBodyDecoder::new(20); 431 /// let (text, _) = decoder.decode(bytes); 432 /// assert!(text.is_partial()); 433 /// 434 /// let bytes = b"text body."; 435 /// let (text, _) = decoder.decode(bytes); 436 /// assert!(!text.is_partial()); 437 /// ``` is_partial(&self) -> bool438 pub fn is_partial(&self) -> bool { 439 !self.is_complete() 440 } 441 442 /// Gets the underlying data of this `Text`. The returned data is a part 443 /// of the body data. 444 /// 445 /// # Examples 446 /// 447 /// ``` 448 /// use ylong_http::body::TextBodyDecoder; 449 /// 450 /// let bytes = b"This is a text body."; 451 /// let mut decoder = TextBodyDecoder::new(20); 452 /// let (text, _) = decoder.decode(bytes); 453 /// assert_eq!(text.data(), b"This is a text body."); 454 /// ``` data(&self) -> &[u8]455 pub fn data(&self) -> &[u8] { 456 self.data 457 } 458 complete(data: &'a [u8]) -> Self459 pub(crate) fn complete(data: &'a [u8]) -> Self { 460 Self { 461 state: TextState::Complete, 462 data, 463 } 464 } 465 partial(data: &'a [u8]) -> Self466 pub(crate) fn partial(data: &'a [u8]) -> Self { 467 Self { 468 state: TextState::Partial, 469 data, 470 } 471 } 472 } 473 474 #[derive(Debug)] 475 enum TextState { 476 Partial, 477 Complete, 478 } 479 480 #[cfg(test)] 481 mod ut_text { 482 use crate::body::text::{TextBody, TextBodyDecoder}; 483 484 /// UT test cases for `TextBody::from_bytes`. 485 /// 486 /// # Brief 487 /// 1. Calls `TextBody::from_bytes()` to create a `TextBody`. 488 #[test] ut_text_body_from_bytes()489 fn ut_text_body_from_bytes() { 490 let bytes = b"Hello World!"; 491 let _body = TextBody::from_bytes(bytes); 492 // Success if no panic. 493 } 494 495 /// UT test cases for `TextBody::from_reader`. 496 /// 497 /// # Brief 498 /// 1. Calls `TextBody::from_reader()` to create a `TextBody`. 499 #[test] ut_text_body_from_reader()500 fn ut_text_body_from_reader() { 501 let reader = "Hello World!".as_bytes(); 502 let _body = TextBody::from_reader(reader); 503 // Success if no panic. 504 } 505 506 /// UT test cases for `TextBody::from_async_reader`. 507 /// 508 /// # Brief 509 /// 1. Calls `TextBody::from_async_reader()` to create a `TextBody`. 510 #[test] ut_text_body_from_async_reader()511 fn ut_text_body_from_async_reader() { 512 let reader = "Hello World!".as_bytes(); 513 let _body = TextBody::from_async_reader(reader); 514 // Success if no panic. 515 } 516 517 /// UT test cases for `sync_impl::Body::data` of `TextBody<FromBytes<'_>>`. 518 /// 519 /// # Brief 520 /// 1. Creates a `TextBody<FromBytes<'_>>`. 521 /// 2. Calls its `sync_impl::Body::data` method and then checks the results. 522 #[test] ut_text_body_from_bytes_syn_data()523 fn ut_text_body_from_bytes_syn_data() { 524 use crate::body::sync_impl::Body; 525 526 let bytes = b"Hello World!"; 527 let mut body = TextBody::from_bytes(bytes); 528 let mut buf = [0u8; 5]; 529 530 let size = body.data(&mut buf).expect("First read failed."); 531 assert_eq!(size, 5); 532 assert_eq!(&buf[..size], b"Hello"); 533 534 let size = body.data(&mut buf).expect("Second read failed."); 535 assert_eq!(size, 5); 536 assert_eq!(&buf[..size], b" Worl"); 537 538 let size = body.data(&mut buf).expect("Third read failed."); 539 assert_eq!(size, 2); 540 assert_eq!(&buf[..size], b"d!"); 541 } 542 543 /// UT test cases for `async_impl::Body::data` of `TextBody<FromBytes<'_>>`. 544 /// 545 /// # Brief 546 /// 1. Creates a `TextBody<FromBytes<'_>>`. 547 /// 2. Calls its `async_impl::Body::data` method and then checks the 548 /// results. 549 #[cfg(feature = "ylong_base")] 550 #[test] ut_text_body_from_bytes_asyn_data()551 fn ut_text_body_from_bytes_asyn_data() { 552 let handle = ylong_runtime::spawn(async move { 553 text_body_from_bytes_asyn_data().await; 554 }); 555 ylong_runtime::block_on(handle).unwrap(); 556 } 557 558 #[cfg(feature = "ylong_base")] text_body_from_bytes_asyn_data()559 async fn text_body_from_bytes_asyn_data() { 560 use crate::body::async_impl::Body; 561 562 let bytes = b"Hello World!"; 563 let mut body = TextBody::from_bytes(bytes); 564 let mut buf = [0u8; 5]; 565 566 let size = body.data(&mut buf).await.expect("First read failed."); 567 assert_eq!(size, 5); 568 assert_eq!(&buf[..size], b"Hello"); 569 570 let size = body.data(&mut buf).await.expect("Second read failed."); 571 assert_eq!(size, 5); 572 assert_eq!(&buf[..size], b" Worl"); 573 574 let size = body.data(&mut buf).await.expect("Third read failed."); 575 assert_eq!(size, 2); 576 assert_eq!(&buf[..size], b"d!"); 577 } 578 579 /// UT test cases for `sync_impl::Body::data` of `TextBody<FromReader<T>>`. 580 /// 581 /// # Brief 582 /// 1. Creates a `TextBody<FromReader<T>>`. 583 /// 2. Calls its `sync_impl::Body::data` method and then checks the results. 584 #[test] ut_text_body_from_reader_syn_data()585 fn ut_text_body_from_reader_syn_data() { 586 use crate::body::sync_impl::Body; 587 588 let reader = "Hello World!".as_bytes(); 589 let mut body = TextBody::from_reader(reader); 590 let mut buf = [0u8; 5]; 591 592 let size = body.data(&mut buf).expect("First read failed."); 593 assert_eq!(size, 5); 594 assert_eq!(&buf[..size], b"Hello"); 595 596 let size = body.data(&mut buf).expect("Second read failed."); 597 assert_eq!(size, 5); 598 assert_eq!(&buf[..size], b" Worl"); 599 600 let size = body.data(&mut buf).expect("Third read failed."); 601 assert_eq!(size, 2); 602 assert_eq!(&buf[..size], b"d!"); 603 } 604 605 /// UT test cases for `async_impl::Body::data` of 606 /// `TextBody<FromAsyncReader<T>>`. 607 /// 608 /// # Brief 609 /// 1. Creates a `TextBody<FromAsyncReader<T>>`. 610 /// 2. Calls its `async_impl::Body::data` method and then checks the 611 /// results. 612 #[cfg(feature = "ylong_base")] 613 #[test] ut_text_body_from_async_reader_asyn_data()614 fn ut_text_body_from_async_reader_asyn_data() { 615 let handle = ylong_runtime::spawn(async move { 616 text_body_from_async_reader_asyn_data().await; 617 }); 618 ylong_runtime::block_on(handle).unwrap(); 619 } 620 621 #[cfg(feature = "ylong_base")] text_body_from_async_reader_asyn_data()622 async fn text_body_from_async_reader_asyn_data() { 623 use crate::body::async_impl::Body; 624 625 let reader = "Hello World!".as_bytes(); 626 let mut body = TextBody::from_async_reader(reader); 627 let mut buf = [0u8; 5]; 628 629 let size = body.data(&mut buf).await.expect("First read failed."); 630 assert_eq!(size, 5); 631 assert_eq!(&buf[..size], b"Hello"); 632 633 let size = body.data(&mut buf).await.expect("Second read failed."); 634 assert_eq!(size, 5); 635 assert_eq!(&buf[..size], b" Worl"); 636 637 let size = body.data(&mut buf).await.expect("Third read failed."); 638 assert_eq!(size, 2); 639 assert_eq!(&buf[..size], b"d!"); 640 } 641 642 /// UT test cases for `TextBodyDecoder::decode`. 643 /// 644 /// # Brief 645 /// 1. Creates a `TextBodyDecoder` by calling `TextBodyDecoder::new`. 646 /// 2. Decodes text body by calling `TextBodyDecoder::decode` 647 /// 3. Checks if the test result is correct. 648 #[test] ut_text_body_decoder_decode()649 fn ut_text_body_decoder_decode() { 650 // Test 1: 651 let bytes = b"this is the text body! and this is remaining data"; 652 let mut decoder = TextBodyDecoder::new(22); 653 let (text, left) = decoder.decode(&bytes[..4]); 654 assert!(text.is_partial()); 655 assert_eq!(text.data(), b"this"); 656 assert!(left.is_empty()); 657 658 let (text, left) = decoder.decode(&bytes[4..11]); 659 assert!(text.is_partial()); 660 assert_eq!(text.data(), b" is the"); 661 assert!(left.is_empty()); 662 663 let (text, left) = decoder.decode(&bytes[11..26]); 664 assert!(text.is_complete()); 665 assert_eq!(text.data(), b" text body!"); 666 assert_eq!(left, b" and"); 667 668 let (text, left) = decoder.decode(&bytes[26..]); 669 assert!(text.is_complete()); 670 assert!(text.data().is_empty()); 671 assert_eq!(left, b" this is remaining data"); 672 673 // Test 2: 674 let bytes = b"this is the text body! And this is remaining data"; 675 let mut decoder = TextBodyDecoder::new(22); 676 let (text, left) = decoder.decode(bytes); 677 assert!(text.is_complete()); 678 assert_eq!(text.data(), b"this is the text body!"); 679 assert_eq!(left, b" And this is remaining data"); 680 } 681 } 682