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::convert::Infallible; 15 use core::ops::{Deref, DerefMut}; 16 use core::pin::Pin; 17 use core::str::from_utf8_unchecked; 18 use core::task::{Context, Poll}; 19 use std::any::Any; 20 use std::collections::HashMap; 21 use std::convert::{TryFrom, TryInto}; 22 use std::future::Future; 23 use std::io::{Error, Read}; 24 25 use super::origin::{FromAsyncReader, FromBytes, FromReader}; 26 use super::{async_impl, sync_impl}; 27 use crate::body::origin::FromAsyncBody; 28 use crate::error::{ErrorKind, HttpError}; 29 use crate::headers::{Header, HeaderName, HeaderValue, Headers}; 30 use crate::{AsyncRead, AsyncReadExt, ReadBuf}; 31 32 /// A chunk body is used to encode body to send message by chunk in `HTTP/1.1` 33 /// format. 34 /// 35 /// This chunk body encoder supports you to use the chunk encode method multiple 36 /// times to output the result in multiple bytes slices. 37 /// 38 /// # Examples 39 /// 40 /// ``` 41 /// use ylong_http::body::sync_impl::Body; 42 /// use ylong_http::body::ChunkBody; 43 /// 44 /// let content = "aaaaa bbbbb ccccc ddddd"; 45 /// // Gets `ChunkBody` 46 /// let mut task = ChunkBody::from_bytes(content.as_bytes()); 47 /// let mut user_slice = [0_u8; 10]; 48 /// let mut output_vec = vec![]; 49 /// 50 /// // First encoding, user_slice is filled. 51 /// let size = task.data(user_slice.as_mut_slice()).unwrap(); 52 /// assert_eq!(&user_slice[..size], "17\r\naaaaa ".as_bytes()); 53 /// output_vec.extend_from_slice(user_slice.as_mut_slice()); 54 /// 55 /// // Second encoding, user_slice is filled. 56 /// let size = task.data(user_slice.as_mut_slice()).unwrap(); 57 /// assert_eq!(&user_slice[..size], "bbbbb cccc".as_bytes()); 58 /// output_vec.extend_from_slice(user_slice.as_mut_slice()); 59 /// 60 /// // Third encoding, user_slice is filled. 61 /// let size = task.data(user_slice.as_mut_slice()).unwrap(); 62 /// assert_eq!(&user_slice[..size], "c ddddd\r\n0".as_bytes()); 63 /// output_vec.extend_from_slice(user_slice.as_mut_slice()); 64 /// 65 /// // Fourth encoding, part of user_slice is filled, this indicates that encoding has ended. 66 /// let size = task.data(user_slice.as_mut_slice()).unwrap(); 67 /// assert_eq!(&user_slice[..size], "\r\n\r\n".as_bytes()); 68 /// output_vec.extend_from_slice(&user_slice[..size]); 69 /// 70 /// // We can assemble temporary data into a complete data. 71 /// let result = "17\r\naaaaa bbbbb ccccc ddddd\r\n0\r\n\r\n"; 72 /// assert_eq!(output_vec.as_slice(), result.as_bytes()); 73 /// ``` 74 pub struct ChunkBody<T> { 75 from: T, 76 trailer_value: Vec<u8>, 77 chunk_data: ChunkData, 78 data_status: DataState, 79 encode_status: EncodeStatus, 80 trailer: EncodeTrailer, 81 } 82 83 const CHUNK_SIZE: usize = 1024; 84 85 struct StatusVar { 86 cnt: usize, 87 data_status: DataState, 88 } 89 90 // Data encoding status 91 enum DataState { 92 // Data encode is processing 93 Partial, 94 // Data encode is completed 95 Complete, 96 // Data encode is finished and return result 97 Finish, 98 } 99 100 // Component encoding status 101 enum TokenStatus<T, E> { 102 // The current component is completely encoded. 103 Complete(T), 104 // The current component is partially encoded. 105 Partial(E), 106 } 107 108 type Token<T> = TokenStatus<usize, T>; 109 110 impl<'a> ChunkBody<FromBytes<'a>> { 111 /// Creates a new `ChunkBody` by `bytes`. 112 /// 113 /// # Examples 114 /// 115 /// ``` 116 /// use ylong_http::body::ChunkBody; 117 /// 118 /// let task = ChunkBody::from_bytes("".as_bytes()); 119 /// ``` from_bytes(bytes: &'a [u8]) -> Self120 pub fn from_bytes(bytes: &'a [u8]) -> Self { 121 ChunkBody { 122 from: FromBytes::new(bytes), 123 trailer_value: vec![], 124 chunk_data: ChunkData::new(vec![]), 125 data_status: DataState::Partial, 126 encode_status: EncodeStatus::new(), 127 trailer: EncodeTrailer::new(), 128 } 129 } 130 chunk_encode(&mut self, src: &[u8], dst: &mut [u8]) -> usize131 fn chunk_encode(&mut self, src: &[u8], dst: &mut [u8]) -> usize { 132 self.encode_status.chunk_last = self.chunk_data.chunk_last; 133 let (output_size, var) = self.encode_status.encode(src, dst); 134 135 if let Some(v) = var { 136 self.chunk_data.chunk_count = v.cnt; 137 self.data_status = v.data_status; 138 } 139 output_size 140 } 141 } 142 143 impl<T: Read> ChunkBody<FromReader<T>> { 144 /// Creates a new `ChunkBody` by `reader`. 145 /// 146 /// # Examples 147 /// 148 /// ``` 149 /// use ylong_http::body::ChunkBody; 150 /// 151 /// let task = ChunkBody::from_reader("".as_bytes()); 152 /// ``` from_reader(reader: T) -> Self153 pub fn from_reader(reader: T) -> Self { 154 ChunkBody { 155 from: FromReader::new(reader), 156 trailer_value: vec![], 157 chunk_data: ChunkData::new(vec![0; CHUNK_SIZE]), 158 data_status: DataState::Partial, 159 encode_status: EncodeStatus::new(), 160 trailer: EncodeTrailer::new(), 161 } 162 } 163 chunk_encode(&mut self, dst: &mut [u8]) -> usize164 fn chunk_encode(&mut self, dst: &mut [u8]) -> usize { 165 self.chunk_encode_reader(dst) 166 } 167 } 168 169 impl<T: AsyncRead + Unpin + Send + Sync> ChunkBody<FromAsyncReader<T>> { 170 /// Creates a new `ChunkBody` by `async reader`. 171 /// 172 /// # Examples 173 /// 174 /// ``` 175 /// use ylong_http::body::ChunkBody; 176 /// 177 /// let task = ChunkBody::from_async_reader("".as_bytes()); 178 /// ``` from_async_reader(reader: T) -> Self179 pub fn from_async_reader(reader: T) -> Self { 180 ChunkBody { 181 from: FromAsyncReader::new(reader), 182 trailer_value: vec![], 183 chunk_data: ChunkData::new(vec![0; CHUNK_SIZE]), 184 data_status: DataState::Partial, 185 encode_status: EncodeStatus::new(), 186 trailer: EncodeTrailer::new(), 187 } 188 } 189 chunk_encode(&mut self, dst: &mut [u8]) -> usize190 fn chunk_encode(&mut self, dst: &mut [u8]) -> usize { 191 self.chunk_encode_reader(dst) 192 } 193 } 194 195 impl<T: async_impl::Body + Unpin> ChunkBody<FromAsyncBody<T>> { 196 /// Creates a new `ChunkBody` by `async body`. 197 /// 198 /// # Examples 199 /// 200 /// ``` 201 /// use ylong_http::body::ChunkBody; 202 /// 203 /// let task = ChunkBody::from_async_body("".as_bytes()); 204 /// ``` from_async_body(body: T) -> Self205 pub fn from_async_body(body: T) -> Self { 206 ChunkBody { 207 from: FromAsyncBody::new(body), 208 trailer_value: vec![], 209 chunk_data: ChunkData::new(vec![0; CHUNK_SIZE]), 210 data_status: DataState::Partial, 211 encode_status: EncodeStatus::new(), 212 trailer: EncodeTrailer::new(), 213 } 214 } 215 chunk_encode(&mut self, dst: &mut [u8]) -> usize216 fn chunk_encode(&mut self, dst: &mut [u8]) -> usize { 217 self.chunk_encode_reader(dst) 218 } 219 } 220 221 impl<'a> sync_impl::Body for ChunkBody<FromBytes<'a>> { 222 type Error = Infallible; 223 data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>224 fn data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { 225 let mut count = 0; 226 while count != buf.len() { 227 let encode_size = match self.data_status { 228 DataState::Partial => self.bytes_encode(&mut buf[count..]), 229 DataState::Complete => self.trailer_encode(&mut buf[count..]), 230 DataState::Finish => return Ok(count), 231 }; 232 count += encode_size; 233 } 234 Ok(buf.len()) 235 } 236 } 237 238 impl<T: Read> sync_impl::Body for ChunkBody<FromReader<T>> { 239 type Error = Error; 240 data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>241 fn data(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { 242 let mut count = 0; 243 while count != buf.len() { 244 let encode_size = match self.data_status { 245 DataState::Partial => { 246 if !self.encode_status.get_flag() { 247 self.encode_status.set_flag(true); 248 self.encode_status.set_chunk_idx(0); 249 self.chunk_data.chunk_last = 250 (*self.from).read(&mut self.chunk_data.chunk_buf).unwrap(); 251 } 252 self.chunk_encode(&mut buf[count..]) 253 } 254 DataState::Complete => self.trailer_encode(&mut buf[count..]), 255 DataState::Finish => { 256 return Ok(count); 257 } 258 }; 259 count += encode_size; 260 } 261 Ok(buf.len()) 262 } 263 } 264 265 impl<'c> async_impl::Body for ChunkBody<FromBytes<'c>> { 266 type Error = Error; 267 poll_data( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>268 fn poll_data( 269 mut self: Pin<&mut Self>, 270 _cx: &mut Context<'_>, 271 buf: &mut [u8], 272 ) -> Poll<Result<usize, Self::Error>> { 273 let mut count = 0; 274 while count != buf.len() { 275 let encode_size: Poll<usize> = match self.data_status { 276 DataState::Partial => Poll::Ready(self.bytes_encode(&mut buf[count..])), 277 DataState::Complete => Poll::Ready(self.trailer_encode(&mut buf[count..])), 278 DataState::Finish => return Poll::Ready(Ok(count)), 279 }; 280 match encode_size { 281 Poll::Ready(size) => { 282 count += size; 283 } 284 Poll::Pending => return Poll::Pending, 285 } 286 } 287 Poll::Ready(Ok(buf.len())) 288 } 289 } 290 291 impl<T: AsyncRead + Unpin + Send + Sync> async_impl::Body for ChunkBody<FromAsyncReader<T>> { 292 type Error = Error; 293 poll_data( self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>294 fn poll_data( 295 self: Pin<&mut Self>, 296 _cx: &mut Context<'_>, 297 buf: &mut [u8], 298 ) -> Poll<Result<usize, Self::Error>> { 299 let chunk_body = self.get_mut(); 300 let mut count = 0; 301 while count != buf.len() { 302 let encode_size = match chunk_body.data_status { 303 DataState::Partial => { 304 if !chunk_body.encode_status.get_flag() { 305 let mut read_buf = ReadBuf::new(&mut chunk_body.chunk_data.chunk_buf); 306 307 match Pin::new(&mut *chunk_body.from).poll_read(_cx, &mut read_buf) { 308 Poll::Ready(Ok(())) => { 309 let size = read_buf.filled().len(); 310 chunk_body.encode_status.set_flag(true); 311 // chunk idx reset zero 312 chunk_body.encode_status.set_chunk_idx(0); 313 chunk_body.chunk_data.chunk_last = size; 314 let data_size = chunk_body.chunk_encode(&mut buf[count..]); 315 Poll::Ready(data_size) 316 } 317 Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), 318 Poll::Pending => Poll::Pending, 319 } 320 } else { 321 Poll::Ready(chunk_body.chunk_encode(&mut buf[count..])) 322 } 323 } 324 DataState::Complete => Poll::Ready(chunk_body.trailer_encode(&mut buf[count..])), 325 DataState::Finish => { 326 return Poll::Ready(Ok(count)); 327 } 328 }; 329 330 match encode_size { 331 Poll::Ready(size) => { 332 count += size; 333 } 334 Poll::Pending => { 335 if count != 0 { 336 return Poll::Ready(Ok(count)); 337 } 338 return Poll::Pending; 339 } 340 } 341 } 342 Poll::Ready(Ok(buf.len())) 343 } 344 } 345 346 impl<T: async_impl::Body> async_impl::Body for ChunkBody<FromAsyncBody<T>> { 347 type Error = T::Error; 348 poll_data( self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize, Self::Error>>349 fn poll_data( 350 self: Pin<&mut Self>, 351 _cx: &mut Context<'_>, 352 buf: &mut [u8], 353 ) -> Poll<Result<usize, Self::Error>> { 354 let chunk_body = self.get_mut(); 355 let mut count = 0; 356 while count != buf.len() { 357 let encode_size = match chunk_body.data_status { 358 DataState::Partial => { 359 if !chunk_body.encode_status.get_flag() { 360 match Pin::new(&mut *chunk_body.from) 361 .poll_data(_cx, &mut chunk_body.chunk_data.chunk_buf) 362 { 363 Poll::Ready(Ok(size)) => { 364 chunk_body.encode_status.set_flag(true); 365 // chunk idx reset zero 366 chunk_body.encode_status.set_chunk_idx(0); 367 chunk_body.chunk_data.chunk_last = size; 368 let data_size = chunk_body.chunk_encode(&mut buf[count..]); 369 Poll::Ready(data_size) 370 } 371 Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), 372 Poll::Pending => Poll::Pending, 373 } 374 } else { 375 Poll::Ready(chunk_body.chunk_encode(&mut buf[count..])) 376 } 377 } 378 DataState::Complete => Poll::Ready(chunk_body.trailer_encode(&mut buf[count..])), 379 DataState::Finish => { 380 return Poll::Ready(Ok(count)); 381 } 382 }; 383 384 match encode_size { 385 Poll::Ready(size) => { 386 count += size; 387 } 388 Poll::Pending => { 389 if count != 0 { 390 return Poll::Ready(Ok(count)); 391 } 392 return Poll::Pending; 393 } 394 } 395 } 396 Poll::Ready(Ok(buf.len())) 397 } 398 } 399 400 impl<'a> ChunkBody<FromBytes<'a>> { bytes_encode(&mut self, dst: &mut [u8]) -> usize401 fn bytes_encode(&mut self, dst: &mut [u8]) -> usize { 402 if !self.encode_status.get_flag() { 403 self.encode_status.set_flag(true); 404 self.encode_status.set_chunk_idx(0); 405 let data_left = self.from.len() - self.chunk_data.chunk_count * CHUNK_SIZE; 406 self.chunk_data.chunk_last = if data_left < CHUNK_SIZE { 407 data_left 408 } else { 409 CHUNK_SIZE 410 }; 411 } 412 let src = &self.from[self.chunk_data.chunk_count * CHUNK_SIZE 413 ..(self.chunk_data.chunk_count * CHUNK_SIZE + self.chunk_data.chunk_last)]; 414 self.chunk_encode(src, dst) 415 } 416 } 417 418 impl<T> ChunkBody<T> { 419 /// Creates a new `Trailer` by `set_trailer`. 420 /// 421 /// # Examples 422 /// 423 /// ``` 424 /// use ylong_http::body::ChunkBody; 425 /// use ylong_http::headers::Headers; 426 /// 427 /// let mut headers = Headers::new(); 428 /// let _ = headers.insert("accept", "text/html"); 429 /// let mut task = ChunkBody::from_bytes("".as_bytes()).set_trailer(headers); 430 /// ``` set_trailer(mut self, trailer_headers: Headers) -> Self431 pub fn set_trailer(mut self, trailer_headers: Headers) -> Self { 432 let mut trailer_vec = vec![]; 433 for (name, value) in trailer_headers.into_iter() { 434 // Operate on each `HeaderName` and `HeaderValue` pair. 435 trailer_vec.extend_from_slice(name.as_bytes()); 436 trailer_vec.extend_from_slice(b":"); 437 // to_string will not return err, so can use unwrap directly 438 trailer_vec.extend_from_slice(value.to_str().unwrap().as_bytes()); 439 trailer_vec.extend_from_slice(b"\r\n"); 440 } 441 self.trailer_value = trailer_vec; 442 self 443 } chunk_encode_reader(&mut self, dst: &mut [u8]) -> usize444 fn chunk_encode_reader(&mut self, dst: &mut [u8]) -> usize { 445 self.encode_status.chunk_last = self.chunk_data.chunk_last; 446 let (output_size, var) = self.encode_status.encode( 447 &self.chunk_data.chunk_buf[..self.chunk_data.chunk_last], 448 dst, 449 ); 450 if let Some(v) = var { 451 self.chunk_data.chunk_count = v.cnt; 452 self.data_status = v.data_status; 453 } 454 output_size 455 } 456 trailer_encode(&mut self, dst: &mut [u8]) -> usize457 fn trailer_encode(&mut self, dst: &mut [u8]) -> usize { 458 let mut src = b"0\r\n".to_vec(); 459 if self.trailer_value.is_empty() { 460 src.extend_from_slice(b"\r\n"); 461 } else { 462 src.extend_from_slice(self.trailer_value.as_slice()); 463 src.extend_from_slice(b"\r\n"); 464 }; 465 match self.trailer.encode(src.as_slice(), dst) { 466 TokenStatus::Complete(output_size) => { 467 self.data_status = DataState::Finish; 468 output_size 469 } 470 TokenStatus::Partial(output_size) => output_size, 471 } 472 } 473 } 474 475 struct ChunkData { 476 chunk_buf: Vec<u8>, 477 chunk_count: usize, 478 chunk_last: usize, 479 } 480 481 impl ChunkData { new(buf: Vec<u8>) -> Self482 fn new(buf: Vec<u8>) -> Self { 483 ChunkData { 484 chunk_buf: buf, 485 chunk_count: 0, 486 chunk_last: 0, 487 } 488 } 489 } 490 491 struct EncodeStatus { 492 chunk_size: usize, 493 chunk_last: usize, 494 chunk_idx: usize, 495 read_flag: bool, 496 src_idx: usize, 497 chunk_status: ChunkState, 498 meta_crlf: EncodeCrlf, 499 data_crlf: EncodeCrlf, 500 finish_crlf: EncodeCrlf, 501 hex: EncodeHex, 502 hex_last: EncodeHex, 503 } 504 505 impl EncodeStatus { new() -> Self506 fn new() -> Self { 507 EncodeStatus { 508 chunk_size: CHUNK_SIZE, 509 chunk_last: 0, 510 chunk_idx: 0, 511 read_flag: false, 512 src_idx: 0, 513 chunk_status: ChunkState::MetaSize, 514 meta_crlf: EncodeCrlf::new(), 515 data_crlf: EncodeCrlf::new(), 516 finish_crlf: EncodeCrlf::new(), 517 hex: EncodeHex::new(format!("{CHUNK_SIZE:x}")), 518 hex_last: EncodeHex::new("".to_string()), 519 } 520 } 521 encode(&mut self, src: &[u8], dst: &mut [u8]) -> (usize, Option<StatusVar>)522 fn encode(&mut self, src: &[u8], dst: &mut [u8]) -> (usize, Option<StatusVar>) { 523 match self.chunk_status { 524 ChunkState::MetaSize => (self.meta_size_encode(dst), None), 525 ChunkState::MetaExt => (0, None), 526 ChunkState::MetaCrlf => (self.meta_crlf_encode(dst), None), 527 ChunkState::Data => { 528 if self.chunk_last != CHUNK_SIZE { 529 self.tail_encode(src, dst) 530 } else { 531 self.data_encode(src, dst) 532 } 533 } 534 ChunkState::DataCrlf => (self.data_crlf_encode(dst), None), 535 ChunkState::Finish => self.finish_encode(dst), 536 } 537 } 538 meta_size_encode(&mut self, dst: &mut [u8]) -> usize539 fn meta_size_encode(&mut self, dst: &mut [u8]) -> usize { 540 if self.chunk_last == CHUNK_SIZE { 541 match self.hex.encode(dst) { 542 TokenStatus::Complete(output_size) => { 543 self.chunk_status = ChunkState::MetaCrlf; 544 self.hex.src_idx = 0; 545 output_size 546 } 547 TokenStatus::Partial(output_size) => output_size, 548 } 549 } else { 550 self.hex_last = EncodeHex::new(format!("{last:x}", last = self.chunk_last)); 551 match self.hex_last.encode(dst) { 552 TokenStatus::Complete(output_size) => { 553 self.chunk_status = ChunkState::MetaCrlf; 554 self.hex_last.src_idx = 0; 555 output_size 556 } 557 TokenStatus::Partial(output_size) => output_size, 558 } 559 } 560 } 561 meta_crlf_encode(&mut self, dst: &mut [u8]) -> usize562 fn meta_crlf_encode(&mut self, dst: &mut [u8]) -> usize { 563 match self.meta_crlf.encode(dst) { 564 TokenStatus::Complete(output_size) => { 565 self.chunk_status = ChunkState::Data; 566 self.meta_crlf.src_idx = 0; 567 output_size 568 } 569 TokenStatus::Partial(output_size) => output_size, 570 } 571 } 572 data_crlf_encode(&mut self, dst: &mut [u8]) -> usize573 fn data_crlf_encode(&mut self, dst: &mut [u8]) -> usize { 574 match self.data_crlf.encode(dst) { 575 TokenStatus::Complete(output_size) => { 576 self.chunk_status = ChunkState::MetaSize; 577 self.data_crlf.src_idx = 0; 578 output_size 579 } 580 TokenStatus::Partial(output_size) => output_size, 581 } 582 } 583 finish_encode(&mut self, dst: &mut [u8]) -> (usize, Option<StatusVar>)584 fn finish_encode(&mut self, dst: &mut [u8]) -> (usize, Option<StatusVar>) { 585 match self.finish_crlf.encode(dst) { 586 TokenStatus::Complete(output_size) => { 587 self.meta_crlf.src_idx = 0; 588 let var = StatusVar { 589 cnt: 0, 590 data_status: DataState::Complete, 591 }; 592 (output_size, Some(var)) 593 } 594 TokenStatus::Partial(output_size) => (output_size, None), 595 } 596 } 597 data_encode(&mut self, src: &[u8], dst: &mut [u8]) -> (usize, Option<StatusVar>)598 fn data_encode(&mut self, src: &[u8], dst: &mut [u8]) -> (usize, Option<StatusVar>) { 599 let mut task = WriteData::new(src, &mut self.chunk_idx, dst); 600 601 match task.write() { 602 TokenStatus::Complete(output_size) => { 603 self.chunk_status = ChunkState::DataCrlf; 604 self.read_flag = false; 605 let var = StatusVar { 606 cnt: 1, 607 data_status: DataState::Partial, 608 }; 609 (output_size, Some(var)) 610 } 611 TokenStatus::Partial(output_size) => (output_size, None), 612 } 613 } 614 tail_encode(&mut self, src: &[u8], dst: &mut [u8]) -> (usize, Option<StatusVar>)615 fn tail_encode(&mut self, src: &[u8], dst: &mut [u8]) -> (usize, Option<StatusVar>) { 616 let mut task = WriteData::new(src, &mut self.chunk_idx, dst); 617 match task.write() { 618 TokenStatus::Complete(output_size) => { 619 self.chunk_status = ChunkState::Finish; 620 self.read_flag = false; 621 let var = StatusVar { 622 cnt: 0, 623 data_status: DataState::Partial, 624 }; 625 (output_size, Some(var)) 626 } 627 TokenStatus::Partial(output_size) => (output_size, None), 628 } 629 } 630 get_flag(&mut self) -> bool631 fn get_flag(&mut self) -> bool { 632 self.read_flag 633 } 634 set_flag(&mut self, flag: bool)635 fn set_flag(&mut self, flag: bool) { 636 self.read_flag = flag; 637 } 638 set_chunk_idx(&mut self, num: usize)639 fn set_chunk_idx(&mut self, num: usize) { 640 self.chunk_idx = num; 641 } 642 } 643 644 struct EncodeHex { 645 inner: String, 646 src_idx: usize, 647 } 648 649 impl EncodeHex { new(hex: String) -> Self650 fn new(hex: String) -> Self { 651 Self { 652 inner: hex, 653 src_idx: 0, 654 } 655 } 656 encode(&mut self, buf: &mut [u8]) -> Token<usize>657 fn encode(&mut self, buf: &mut [u8]) -> Token<usize> { 658 let hex = self.inner.as_bytes(); 659 let mut task = WriteData::new(hex, &mut self.src_idx, buf); 660 task.write() 661 } 662 } 663 664 struct EncodeCrlf { 665 src_idx: usize, 666 } 667 668 impl EncodeCrlf { new() -> Self669 fn new() -> Self { 670 Self { src_idx: 0 } 671 } 672 encode(&mut self, buf: &mut [u8]) -> Token<usize>673 fn encode(&mut self, buf: &mut [u8]) -> Token<usize> { 674 let crlf = "\r\n".as_bytes(); 675 let mut task = WriteData::new(crlf, &mut self.src_idx, buf); 676 task.write() 677 } 678 } 679 680 struct EncodeTrailer { 681 src_idx: usize, 682 } 683 684 impl EncodeTrailer { new() -> Self685 fn new() -> Self { 686 Self { src_idx: 0 } 687 } 688 encode(&mut self, src: &[u8], buf: &mut [u8]) -> Token<usize>689 fn encode(&mut self, src: &[u8], buf: &mut [u8]) -> Token<usize> { 690 let mut task = WriteData::new(src, &mut self.src_idx, buf); 691 task.write() 692 } 693 } 694 695 struct WriteData<'a> { 696 src: &'a [u8], 697 src_idx: &'a mut usize, 698 dst: &'a mut [u8], 699 } 700 701 impl<'a> WriteData<'a> { new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self702 fn new(src: &'a [u8], src_idx: &'a mut usize, dst: &'a mut [u8]) -> Self { 703 WriteData { src, src_idx, dst } 704 } 705 write(&mut self) -> Token<usize>706 fn write(&mut self) -> Token<usize> { 707 let src_idx = *self.src_idx; 708 let input_len = self.src.len() - src_idx; 709 let output_len = self.dst.len(); 710 let num = std::io::Read::read(&mut &self.src[src_idx..], self.dst).unwrap(); 711 if output_len >= input_len { 712 *self.src_idx += num; 713 return TokenStatus::Complete(num); 714 } 715 *self.src_idx += num; 716 TokenStatus::Partial(num) 717 } 718 } 719 720 // Stage of decode chunks, The elements of the chunk-body are as follows: 721 // |======================================================================== 722 // | chunked-body = *chunk | 723 // | last-chunk | 724 // | trailer-section | 725 // | CRLF | 726 // | | 727 // | chunk = chunk-size [ chunk-ext ] CRLF | 728 // | chunk-data CRLF | 729 // | chunk-size = 1*HEXDIG | 730 // | last-chunk = 1*("0") [ chunk-ext ] CRLF | 731 // | | 732 // | chunk-data = 1*OCTET ; a sequence of chunk-size octets | 733 // | | 734 // | chunk-ext = *( BWS ";" BWS chunk-ext-name | 735 // | [ BWS "=" BWS chunk-ext-val ] ) | 736 // | | 737 // | chunk-ext-name = token | 738 // | chunk-ext-val = token / quoted-string | 739 // |======================================================================== 740 enum Stage { 741 Size, 742 Extension, 743 SizeEnd, 744 Data, 745 DataEnd, 746 TrailerCrlf, 747 TrailerData, 748 TrailerEndCrlf, 749 } 750 751 /// Chunk-ext part of a chunk, 752 /// Currently, the `ChunkBodyDecoder` does not decode the chunk-ext part. 753 /// Therefore, the chunk-ext key-value pair cannot be inserted or extracted. 754 #[derive(Debug, Default, Eq, PartialEq)] 755 pub struct ChunkExt { 756 map: HashMap<String, String>, 757 } 758 759 impl ChunkExt { 760 /// Constructor of `ChunkExt` new() -> Self761 pub fn new() -> Self { 762 ChunkExt { 763 map: HashMap::new(), 764 } 765 } 766 } 767 768 /// Decode state of the chunk buffer. 769 /// When chunks in the buffer end in different elements, `ChunkBodyDecoder` 770 /// returns different `ChunkState`, as shown in the following figure: 771 /// > ```trust 772 /// > Meta: `chunk-size [ chunk-ext ] CRLF` 773 /// > Partial: `chunk-size [ chunk-ext ] CRLF chunk-data` 774 /// > Complete: `chunk-size [ chunk-ext ] CRLF chunk-data CRLF` 775 /// > ``` 776 #[derive(Debug, Eq, PartialEq)] 777 pub enum ChunkState { 778 /// State of `chunk-size` 779 MetaSize, 780 /// State of `chunk-ext` 781 MetaExt, 782 /// CRLF 783 MetaCrlf, 784 /// State of `chunk-data` 785 Data, 786 /// CRLF 787 DataCrlf, 788 /// End 789 Finish, 790 } 791 792 /// Decode result of the chunk buffer, contains all chunks in a buffer. 793 #[derive(Debug, Eq, PartialEq)] 794 pub struct Chunks<'a> { 795 chunks: Vec<Chunk<'a>>, 796 } 797 798 /// An iterator of `Chunks`. 799 pub struct ChunksIter<'a> { 800 iter: core::slice::Iter<'a, Chunk<'a>>, 801 } 802 803 /// An iterator that moves out of a `Chunks`. 804 pub struct ChunksIntoIter<'a> { 805 into_iter: std::vec::IntoIter<Chunk<'a>>, 806 } 807 808 impl ChunksIter<'_> { new<'a>(iter: core::slice::Iter<'a, Chunk<'a>>) -> ChunksIter<'a>809 fn new<'a>(iter: core::slice::Iter<'a, Chunk<'a>>) -> ChunksIter<'a> { 810 ChunksIter { iter } 811 } 812 } 813 814 impl<'a> Deref for ChunksIter<'a> { 815 type Target = core::slice::Iter<'a, Chunk<'a>>; 816 deref(&self) -> &Self::Target817 fn deref(&self) -> &Self::Target { 818 &self.iter 819 } 820 } 821 822 impl<'a> DerefMut for ChunksIter<'a> { deref_mut(&mut self) -> &mut Self::Target823 fn deref_mut(&mut self) -> &mut Self::Target { 824 &mut self.iter 825 } 826 } 827 828 impl ChunksIntoIter<'_> { new(into_iter: std::vec::IntoIter<Chunk>) -> ChunksIntoIter829 fn new(into_iter: std::vec::IntoIter<Chunk>) -> ChunksIntoIter { 830 ChunksIntoIter { into_iter } 831 } 832 } 833 834 impl<'a> Iterator for ChunksIntoIter<'a> { 835 type Item = Chunk<'a>; 836 next(&mut self) -> Option<Self::Item>837 fn next(&mut self) -> Option<Self::Item> { 838 self.into_iter.next() 839 } 840 } 841 842 impl<'a> Deref for ChunksIntoIter<'a> { 843 type Target = std::vec::IntoIter<Chunk<'a>>; 844 deref(&self) -> &Self::Target845 fn deref(&self) -> &Self::Target { 846 &self.into_iter 847 } 848 } 849 850 impl<'b> Chunks<'b> { 851 /// Returns an `ChunksIter` iter(&self) -> ChunksIter852 pub fn iter(&self) -> ChunksIter { 853 ChunksIter::new(self.chunks.iter()) 854 } 855 new() -> Self856 fn new() -> Self { 857 Chunks { chunks: vec![] } 858 } 859 push<'a: 'b>(&mut self, chunk: Chunk<'a>)860 fn push<'a: 'b>(&mut self, chunk: Chunk<'a>) { 861 self.chunks.push(chunk) 862 } 863 } 864 865 impl<'a> IntoIterator for Chunks<'a> { 866 type Item = Chunk<'a>; 867 type IntoIter = ChunksIntoIter<'a>; 868 into_iter(self) -> Self::IntoIter869 fn into_iter(self) -> Self::IntoIter { 870 ChunksIntoIter::new(self.chunks.into_iter()) 871 } 872 } 873 874 /// Chunk instance, Indicates a chunk. 875 /// After a decode, the `ChunkBodyDecoder` returns a `Chunk` regardless of 876 /// whether a chunk is completely decoded. The decode status is recorded by the 877 /// `state` variable. 878 #[derive(Debug, Eq, PartialEq)] 879 pub struct Chunk<'a> { 880 id: usize, 881 state: ChunkState, 882 size: usize, 883 extension: ChunkExt, 884 data: &'a [u8], 885 trailer: Option<&'a [u8]>, 886 } 887 888 impl Chunk<'_> { set_id(&mut self, id: usize)889 fn set_id(&mut self, id: usize) { 890 self.id = id; 891 } 892 is_complete(&self) -> bool893 fn is_complete(&self) -> bool { 894 matches!(self.state, ChunkState::Finish) 895 } 896 897 /// Get the id of chunk-data. id(&self) -> usize898 pub fn id(&self) -> usize { 899 self.id 900 } 901 902 /// Get the immutable reference of a state. state(&self) -> &ChunkState903 pub fn state(&self) -> &ChunkState { 904 &self.state 905 } 906 907 /// Get the size of chunk-data, 908 /// If the size part of a chunk is not completely decoded, the value of size 909 /// is 0. size(&self) -> usize910 pub fn size(&self) -> usize { 911 self.size 912 } 913 914 /// Get the immutable reference of chunk-ext. 915 /// Currently, only one empty ChunkExt is contained. extension(&self) -> &ChunkExt916 pub fn extension(&self) -> &ChunkExt { 917 &self.extension 918 } 919 920 /// Get the chunk-data. 921 /// When the state is partial, only partial data is returned. data(&self) -> &[u8]922 pub fn data(&self) -> &[u8] { 923 self.data 924 } 925 /// Get the trailer. trailer(&self) -> Option<&[u8]>926 pub fn trailer(&self) -> Option<&[u8]> { 927 self.trailer 928 } 929 } 930 931 /// Chunk decoder. 932 /// The decoder decode only all chunks and last-chunk in chunk-body and does not 933 /// decode subsequent trailer-section. The decoder maintains a state saving 934 /// decode phase. When a chunk is not completely decoded or a decoding exception 935 /// occurs, the state is not reset. 936 pub struct ChunkBodyDecoder { 937 chunk_num: usize, 938 total_size: usize, 939 rest_size: usize, 940 hex_count: i64, 941 trailer: Vec<u8>, 942 cr_meet: bool, 943 chunk_flag: bool, 944 is_last_chunk: bool, 945 is_chunk_trailer: bool, 946 is_trailer: bool, 947 is_trailer_crlf: bool, 948 stage: Stage, 949 } 950 951 impl Default for ChunkBodyDecoder { default() -> Self952 fn default() -> Self { 953 Self::new() 954 } 955 } 956 957 impl ChunkBodyDecoder { 958 /// Constructor of `ChunkBodyDecoder` bytes decoder. 959 /// Initial stage is `Size` new() -> ChunkBodyDecoder960 pub fn new() -> ChunkBodyDecoder { 961 ChunkBodyDecoder { 962 chunk_num: 0, 963 total_size: 0, 964 rest_size: 0, 965 hex_count: 0, 966 trailer: vec![], 967 cr_meet: false, 968 chunk_flag: false, 969 is_last_chunk: false, 970 is_chunk_trailer: false, 971 is_trailer: false, 972 is_trailer_crlf: false, 973 stage: Stage::Size, 974 } 975 } 976 977 /// Initial trailer settings for check whether body contain trailer. contains_trailer(mut self, contain_trailer: bool) -> Self978 pub fn contains_trailer(mut self, contain_trailer: bool) -> Self { 979 self.is_trailer = contain_trailer; 980 self 981 } 982 merge_trailer(&mut self, chunk: &Chunk)983 fn merge_trailer(&mut self, chunk: &Chunk) { 984 if chunk.state() == &ChunkState::Finish || chunk.state() == &ChunkState::DataCrlf { 985 self.trailer.extend_from_slice(chunk.trailer().unwrap()); 986 if !self.trailer.is_empty() { 987 self.trailer.extend_from_slice(b"\r\n"); 988 } 989 } else { 990 self.trailer.extend_from_slice(chunk.trailer().unwrap()); 991 } 992 } 993 /// Decode interface of the chunk decoder. 994 /// It transfers a u8 slice pointing to the chunk data and returns the data 995 /// of a chunk and the remaining data. When the data in the u8 slice is 996 /// not completely decoded for a chunk, An empty u8 slice is returned 997 /// for the remaining data. 998 /// 999 /// # Examples 1000 /// 1001 /// ``` 1002 /// use ylong_http::body::{Chunk, ChunkBodyDecoder, ChunkExt, ChunkState}; 1003 /// let mut decoder = ChunkBodyDecoder::new(); 1004 /// let chunk_body_bytes = "\ 1005 /// 5\r\n\ 1006 /// hello\r\n\ 1007 /// 000; message = last\r\n\ 1008 /// \r\n\ 1009 /// " 1010 /// .as_bytes(); 1011 /// let (chunks, rest) = decoder.decode(chunk_body_bytes).unwrap(); 1012 /// assert_eq!(chunks.iter().len(), 2); 1013 /// let chunk = chunks.iter().next().unwrap(); 1014 /// assert_eq!( 1015 /// ( 1016 /// chunk.id(), 1017 /// chunk.state(), 1018 /// chunk.size(), 1019 /// chunk.extension(), 1020 /// chunk.data() 1021 /// ), 1022 /// ( 1023 /// 0, 1024 /// &ChunkState::Finish, 1025 /// 5, 1026 /// &ChunkExt::new(), 1027 /// "hello".as_bytes() 1028 /// ) 1029 /// ); 1030 /// ``` decode<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunks<'a>, &'a [u8]), HttpError>1031 pub fn decode<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunks<'a>, &'a [u8]), HttpError> { 1032 let mut results = Chunks::new(); 1033 let mut remains = buf; 1034 loop { 1035 let (mut chunk, rest) = match self.stage { 1036 Stage::Size => self.decode_size(remains), 1037 Stage::Extension => self.skip_extension(remains), 1038 Stage::SizeEnd => self.skip_crlf(remains), 1039 Stage::Data => self.decode_data(remains), 1040 Stage::DataEnd => self.skip_last_crlf(&remains[..0], remains), 1041 Stage::TrailerCrlf => self.skip_trailer_crlf(remains), 1042 Stage::TrailerData => self.decode_trailer_data(remains), 1043 Stage::TrailerEndCrlf => self.skip_trailer_last_crlf(&remains[..0], remains), 1044 }?; 1045 1046 chunk.set_id(self.chunk_num); 1047 1048 if chunk.trailer.is_some() { 1049 self.merge_trailer(&chunk); 1050 } 1051 1052 remains = rest; 1053 match (chunk.is_complete(), self.is_last_chunk) { 1054 (false, _) => { 1055 if self.is_chunk_trailer 1056 && (chunk.state == ChunkState::Data || chunk.state == ChunkState::DataCrlf) 1057 { 1058 results.push(chunk); 1059 self.chunk_num += 1; 1060 if remains.is_empty() { 1061 break; 1062 } 1063 } else { 1064 results.push(chunk); 1065 break; 1066 } 1067 } 1068 (true, true) => { 1069 results.push(chunk); 1070 self.is_last_chunk = false; 1071 self.chunk_num = 0; 1072 break; 1073 } 1074 (true, false) => { 1075 results.push(chunk); 1076 self.chunk_num += 1; 1077 if remains.is_empty() { 1078 break; 1079 } 1080 } 1081 } 1082 } 1083 Ok((results, remains)) 1084 } 1085 1086 /// Get trailer headers. get_trailer(&self) -> Result<Option<Headers>, HttpError>1087 pub fn get_trailer(&self) -> Result<Option<Headers>, HttpError> { 1088 if self.trailer.is_empty() { 1089 return Ok(None); 1090 } 1091 1092 let mut colon = 0; 1093 let mut lf = 0; 1094 let mut trailer_header_name = HeaderName::from_bytes(b"")?; 1095 let mut trailer_headers = Headers::new(); 1096 for (i, b) in self.trailer.iter().enumerate() { 1097 if *b == b' ' { 1098 continue; 1099 } 1100 1101 if *b == b':' { 1102 colon = i; 1103 if lf == 0 { 1104 let trailer_name = &self.trailer[..colon]; 1105 trailer_header_name = HeaderName::from_bytes(trailer_name)?; 1106 } else { 1107 let trailer_name = &self.trailer[lf + 1..colon]; 1108 trailer_header_name = HeaderName::from_bytes(trailer_name)?; 1109 } 1110 continue; 1111 } 1112 1113 if *b == b'\n' { 1114 if &self.trailer[i - 2..i - 1] == "\n".as_bytes() { 1115 break; 1116 } 1117 lf = i; 1118 let trailer_value = &self.trailer[colon + 1..lf - 1]; 1119 let trailer_header_value = HeaderValue::from_bytes(trailer_value)?; 1120 let _ = trailer_headers.insert::<HeaderName, HeaderValue>( 1121 trailer_header_name.clone(), 1122 trailer_header_value.clone(), 1123 )?; 1124 } 1125 } 1126 1127 Ok(Some(trailer_headers)) 1128 } 1129 hex_to_decimal(mut count: i64, num: i64) -> Result<i64, HttpError>1130 fn hex_to_decimal(mut count: i64, num: i64) -> Result<i64, HttpError> { 1131 count = count 1132 .checked_mul(16) 1133 .ok_or_else(|| HttpError::from(ErrorKind::InvalidInput))?; 1134 count 1135 .checked_add(num) 1136 .ok_or_else(|| HttpError::from(ErrorKind::InvalidInput)) 1137 } 1138 decode_size<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1139 fn decode_size<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1140 self.stage = Stage::Size; 1141 if buf.is_empty() { 1142 return Ok(( 1143 Chunk { 1144 id: 0, 1145 state: ChunkState::MetaSize, 1146 size: self.total_size, 1147 extension: ChunkExt::new(), 1148 data: &buf[..0], 1149 trailer: None, 1150 }, 1151 buf, 1152 )); 1153 } 1154 self.chunk_flag = false; 1155 for (i, &b) in buf.iter().enumerate() { 1156 match b { 1157 b'0' => { 1158 if buf.len() <= i + 1 { 1159 self.hex_count = Self::hex_to_decimal(self.hex_count, 0_i64)?; 1160 continue; 1161 } 1162 if buf[i + 1] != b';' && buf[i + 1] != b' ' && buf[i + 1] != b'\r' { 1163 self.hex_count = Self::hex_to_decimal(self.hex_count, 0_i64)?; 1164 continue; 1165 } 1166 if self.is_trailer && !self.chunk_flag { 1167 self.is_chunk_trailer = true; 1168 return self.skip_extension(&buf[i..]); 1169 } else { 1170 self.hex_count = Self::hex_to_decimal(self.hex_count, 0_i64)?; 1171 continue; 1172 } 1173 } 1174 b'1'..=b'9' => { 1175 self.hex_count = Self::hex_to_decimal(self.hex_count, b as i64 - '0' as i64)?; 1176 self.chunk_flag = true; 1177 continue; 1178 } 1179 1180 b'a'..=b'f' => { 1181 self.hex_count = 1182 Self::hex_to_decimal(self.hex_count, b as i64 - 'a' as i64 + 10i64)?; 1183 self.chunk_flag = true; 1184 continue; 1185 } 1186 b'A'..=b'F' => { 1187 self.hex_count = 1188 Self::hex_to_decimal(self.hex_count, b as i64 - 'A' as i64 + 10i64)?; 1189 self.chunk_flag = true; 1190 continue; 1191 } 1192 b' ' | b'\t' | b';' | b'\r' | b'\n' => { 1193 if self.is_chunk_trailer { 1194 return self.skip_trailer_crlf(&buf[i..]); 1195 } else { 1196 self.total_size = self.hex_count as usize; 1197 self.hex_count = 0; 1198 // Decode to the last chunk 1199 return if self.total_size == 0 { 1200 self.is_last_chunk = true; 1201 self.skip_extension(&buf[i..]) 1202 } else { 1203 self.rest_size = self.total_size; 1204 self.skip_extension(&buf[i..]) 1205 }; 1206 } 1207 } 1208 _ => return Err(ErrorKind::InvalidInput.into()), 1209 } 1210 } 1211 Ok(( 1212 Chunk { 1213 id: 0, 1214 state: ChunkState::MetaSize, 1215 size: self.total_size, 1216 extension: ChunkExt::new(), 1217 data: &buf[..0], 1218 trailer: None, 1219 }, 1220 &buf[buf.len()..], 1221 )) 1222 } 1223 skip_extension<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1224 fn skip_extension<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1225 self.stage = Stage::Extension; 1226 if self.is_chunk_trailer { 1227 for (i, &b) in buf.iter().enumerate() { 1228 match b { 1229 b'\r' => { 1230 if self.cr_meet { 1231 return Err(ErrorKind::InvalidInput.into()); 1232 } 1233 self.cr_meet = true; 1234 return self.skip_trailer_crlf(&buf[i + 1..]); 1235 } 1236 b'\n' => { 1237 if !self.cr_meet { 1238 return Err(ErrorKind::InvalidInput.into()); 1239 } 1240 self.cr_meet = false; 1241 1242 return self.skip_trailer_crlf(&buf[i..]); 1243 } 1244 _ => {} 1245 } 1246 } 1247 Ok(( 1248 Chunk { 1249 id: 0, 1250 state: ChunkState::MetaExt, 1251 size: self.total_size, 1252 extension: ChunkExt::new(), 1253 data: &buf[..0], 1254 trailer: Some(&buf[..0]), 1255 }, 1256 &buf[buf.len()..], 1257 )) 1258 } else { 1259 for (i, &b) in buf.iter().enumerate() { 1260 match b { 1261 b'\r' => { 1262 if self.cr_meet { 1263 return Err(ErrorKind::InvalidInput.into()); 1264 } 1265 self.cr_meet = true; 1266 return self.skip_crlf(&buf[i + 1..]); 1267 } 1268 b'\n' => { 1269 if !self.cr_meet { 1270 return Err(ErrorKind::InvalidInput.into()); 1271 } 1272 self.cr_meet = false; 1273 return self.skip_crlf(&buf[i..]); 1274 } 1275 _ => {} 1276 } 1277 } 1278 Ok(( 1279 Chunk { 1280 id: 0, 1281 state: ChunkState::MetaExt, 1282 size: self.total_size, 1283 extension: ChunkExt::new(), 1284 data: &buf[..0], 1285 trailer: None, 1286 }, 1287 &buf[buf.len()..], 1288 )) 1289 } 1290 } 1291 skip_crlf<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1292 fn skip_crlf<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1293 self.stage = Stage::SizeEnd; 1294 for (i, &b) in buf.iter().enumerate() { 1295 match b { 1296 b'\r' => { 1297 if self.cr_meet { 1298 // TODO Check whether the state machine needs to be reused after the parsing 1299 // fails and whether the state machine status needs to be adjusted. 1300 return Err(ErrorKind::InvalidInput.into()); 1301 } 1302 self.cr_meet = true; 1303 } 1304 b'\n' => { 1305 if !self.cr_meet { 1306 return Err(ErrorKind::InvalidInput.into()); 1307 } 1308 self.cr_meet = false; 1309 return self.decode_data(&buf[i + 1..]); 1310 } 1311 _ => return Err(ErrorKind::InvalidInput.into()), 1312 } 1313 } 1314 Ok(( 1315 Chunk { 1316 id: 0, 1317 state: ChunkState::MetaCrlf, 1318 size: self.total_size, 1319 extension: ChunkExt::new(), 1320 data: &buf[..0], 1321 trailer: None, 1322 }, 1323 &buf[buf.len()..], 1324 )) 1325 } 1326 skip_trailer_crlf<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1327 fn skip_trailer_crlf<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1328 self.stage = Stage::TrailerCrlf; 1329 for (i, &b) in buf.iter().enumerate() { 1330 match b { 1331 b'\r' => { 1332 if self.cr_meet { 1333 return Err(ErrorKind::InvalidInput.into()); 1334 } 1335 self.cr_meet = true; 1336 } 1337 b'\n' => { 1338 if !self.cr_meet { 1339 return Err(ErrorKind::InvalidInput.into()); 1340 } 1341 self.cr_meet = false; 1342 self.is_trailer_crlf = true; 1343 return self.decode_trailer_data(&buf[i + 1..]); 1344 } 1345 _ => return Err(ErrorKind::InvalidInput.into()), 1346 } 1347 } 1348 Ok(( 1349 Chunk { 1350 id: 0, 1351 state: ChunkState::MetaCrlf, 1352 size: self.total_size, 1353 extension: ChunkExt::new(), 1354 data: &buf[..0], 1355 trailer: Some(&buf[..0]), 1356 }, 1357 &buf[buf.len()..], 1358 )) 1359 } 1360 decode_trailer_data<'a>( &mut self, buf: &'a [u8], ) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1361 fn decode_trailer_data<'a>( 1362 &mut self, 1363 buf: &'a [u8], 1364 ) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1365 self.stage = Stage::TrailerData; 1366 if buf.is_empty() { 1367 return Ok(( 1368 Chunk { 1369 id: 0, 1370 state: ChunkState::Data, 1371 size: 0, 1372 extension: ChunkExt::new(), 1373 data: &buf[..0], 1374 trailer: Some(&buf[..0]), 1375 }, 1376 &buf[buf.len()..], 1377 )); 1378 } 1379 1380 if buf[0] == b'\r' && self.is_trailer_crlf { 1381 self.is_last_chunk = true; 1382 } 1383 1384 for (i, &b) in buf.iter().enumerate() { 1385 match b { 1386 b'\r' => { 1387 if self.cr_meet { 1388 return Err(ErrorKind::InvalidInput.into()); 1389 } 1390 self.cr_meet = true; 1391 return self.skip_trailer_last_crlf(&buf[..i], &buf[i + 1..]); 1392 } 1393 b'\n' => { 1394 if !self.cr_meet { 1395 return Err(ErrorKind::InvalidInput.into()); 1396 } 1397 self.cr_meet = false; 1398 return self.skip_trailer_last_crlf(&buf[..i], &buf[i..]); 1399 } 1400 _ => {} 1401 } 1402 } 1403 self.is_trailer_crlf = false; 1404 Ok(( 1405 Chunk { 1406 id: 0, 1407 state: ChunkState::Data, 1408 size: 0, 1409 extension: ChunkExt::new(), 1410 data: &buf[..0], 1411 trailer: Some(buf), 1412 }, 1413 &buf[buf.len()..], 1414 )) 1415 } 1416 decode_data<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1417 fn decode_data<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1418 self.stage = Stage::Data; 1419 if buf.is_empty() { 1420 return Ok(( 1421 Chunk { 1422 id: 0, 1423 state: ChunkState::Data, 1424 size: self.total_size, 1425 extension: ChunkExt::new(), 1426 data: &buf[..0], 1427 trailer: None, 1428 }, 1429 &buf[buf.len()..], 1430 )); 1431 } 1432 1433 let rest = self.rest_size; 1434 if buf.len() >= rest { 1435 self.rest_size = 0; 1436 self.cr_meet = false; 1437 self.skip_last_crlf(&buf[..rest], &buf[rest..]) 1438 } else { 1439 self.rest_size -= buf.len(); 1440 Ok(( 1441 Chunk { 1442 id: 0, 1443 state: ChunkState::Data, 1444 size: self.total_size, 1445 extension: ChunkExt::new(), 1446 data: buf, 1447 trailer: None, 1448 }, 1449 &buf[buf.len()..], 1450 )) 1451 } 1452 } 1453 skip_trailer_last_crlf<'a>( &mut self, data: &'a [u8], buf: &'a [u8], ) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1454 fn skip_trailer_last_crlf<'a>( 1455 &mut self, 1456 data: &'a [u8], 1457 buf: &'a [u8], 1458 ) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1459 self.stage = Stage::TrailerEndCrlf; 1460 for (i, &b) in buf.iter().enumerate() { 1461 match b { 1462 b'\r' => { 1463 if self.cr_meet { 1464 return Err(ErrorKind::InvalidInput.into()); 1465 } 1466 self.cr_meet = true; 1467 } 1468 b'\n' => { 1469 if !self.cr_meet { 1470 return Err(ErrorKind::InvalidInput.into()); 1471 } 1472 self.cr_meet = false; 1473 return if self.is_last_chunk { 1474 self.stage = Stage::TrailerEndCrlf; 1475 Ok(( 1476 Chunk { 1477 id: 0, 1478 state: ChunkState::Finish, 1479 size: 0, 1480 extension: ChunkExt::new(), 1481 data: &buf[..0], 1482 trailer: Some(&buf[..0]), 1483 }, 1484 &buf[i + 1..], 1485 )) 1486 } else { 1487 self.cr_meet = false; 1488 self.is_trailer_crlf = true; 1489 self.stage = Stage::TrailerData; 1490 let complete_chunk = Chunk { 1491 id: 0, 1492 state: ChunkState::DataCrlf, 1493 size: 0, 1494 extension: ChunkExt::new(), 1495 data: &data[..0], 1496 trailer: Some(data), 1497 }; 1498 return Ok((complete_chunk, &buf[i + 1..])); 1499 }; 1500 } 1501 _ => return Err(ErrorKind::InvalidInput.into()), 1502 } 1503 } 1504 1505 Ok(( 1506 Chunk { 1507 id: 0, 1508 state: ChunkState::DataCrlf, 1509 size: 0, 1510 extension: ChunkExt::new(), 1511 data: &data[..0], 1512 trailer: Some(data), 1513 }, 1514 &buf[buf.len()..], 1515 )) 1516 } 1517 skip_last_crlf<'a>( &mut self, data: &'a [u8], buf: &'a [u8], ) -> Result<(Chunk<'a>, &'a [u8]), HttpError>1518 fn skip_last_crlf<'a>( 1519 &mut self, 1520 data: &'a [u8], 1521 buf: &'a [u8], 1522 ) -> Result<(Chunk<'a>, &'a [u8]), HttpError> { 1523 self.stage = Stage::DataEnd; 1524 for (i, &b) in buf.iter().enumerate() { 1525 match b { 1526 b'\r' => { 1527 if self.cr_meet { 1528 return Err(ErrorKind::InvalidInput.into()); 1529 } 1530 self.cr_meet = true; 1531 } 1532 b'\n' => { 1533 if !self.cr_meet { 1534 return Err(ErrorKind::InvalidInput.into()); 1535 } 1536 self.cr_meet = false; 1537 self.stage = Stage::Size; 1538 let complete_chunk = Chunk { 1539 id: 0, 1540 state: ChunkState::Finish, 1541 size: self.total_size, 1542 extension: ChunkExt::new(), 1543 data, 1544 trailer: None, 1545 }; 1546 self.total_size = 0; 1547 return Ok((complete_chunk, &buf[i + 1..])); 1548 } 1549 _ => return Err(ErrorKind::InvalidInput.into()), 1550 } 1551 } 1552 Ok(( 1553 Chunk { 1554 id: 0, 1555 state: ChunkState::DataCrlf, 1556 size: self.total_size, 1557 extension: ChunkExt::new(), 1558 data, 1559 trailer: None, 1560 }, 1561 &buf[buf.len()..], 1562 )) 1563 } 1564 } 1565 1566 #[cfg(test)] 1567 mod ut_chunk { 1568 use crate::body::chunk::ChunkBody; 1569 use crate::body::sync_impl::Body; 1570 use crate::body::{async_impl, Chunk, ChunkBodyDecoder, ChunkExt, ChunkState, Chunks}; 1571 use crate::error::ErrorKind; 1572 use crate::headers::Headers; 1573 data_message() -> Vec<u8>1574 fn data_message() -> Vec<u8> { 1575 let mut vec = Vec::new(); 1576 for i in 0..=10 { 1577 vec.extend_from_slice(&[i % 10; 100]); 1578 } 1579 vec 1580 } 1581 res_message() -> Vec<u8>1582 fn res_message() -> Vec<u8> { 1583 let mut res = b"400\r\n".to_vec(); 1584 for i in 0..=9 { 1585 res.extend_from_slice(&[i % 10; 100]); 1586 } 1587 res.extend_from_slice(&[0; 24]); 1588 res.extend_from_slice(b"\r\n4c\r\n"); 1589 res.extend_from_slice(&[0; 76]); 1590 res.extend_from_slice(b"\r\n0\r\n\r\n"); 1591 res 1592 } res_trailer_message() -> Vec<u8>1593 fn res_trailer_message() -> Vec<u8> { 1594 let mut res = b"400\r\n".to_vec(); 1595 for i in 0..=9 { 1596 res.extend_from_slice(&[i % 10; 100]); 1597 } 1598 res.extend_from_slice(&[0; 24]); 1599 res.extend_from_slice(b"\r\n4c\r\n"); 1600 res.extend_from_slice(&[0; 76]); 1601 res.extend_from_slice(b"\r\n0\r\n"); 1602 res.extend_from_slice(b"accept:text/html\r\n"); 1603 res.extend_from_slice(b"\r\n"); 1604 res 1605 } 1606 1607 /// UT test cases for `ChunkBody::set_trailer`. 1608 /// 1609 /// # Brief 1610 /// 1. Creates a `ChunkBody` by calling `ChunkBody::set_trailer`. 1611 /// 2. Encodes chunk body by calling `ChunkBody::data` 1612 /// 3. Checks if the test result is correct. 1613 #[test] ut_chunk_body_encode_trailer_0()1614 fn ut_chunk_body_encode_trailer_0() { 1615 let mut headers = Headers::new(); 1616 let _ = headers.insert("accept", "text/html"); 1617 let content = data_message(); 1618 let mut task = ChunkBody::from_bytes(content.as_slice()).set_trailer(headers); 1619 let mut user_slice = [0_u8; 20]; 1620 let mut output_vec = vec![]; 1621 let mut size = user_slice.len(); 1622 while size == user_slice.len() { 1623 size = task.data(user_slice.as_mut_slice()).unwrap(); 1624 output_vec.extend_from_slice(&user_slice[..size]); 1625 } 1626 assert_eq!(output_vec, res_trailer_message()); 1627 } 1628 1629 /// UT test cases for `ChunkBody::data`. 1630 /// 1631 /// # Brief 1632 /// 1. Creates a `ChunkBody` by calling `ChunkBody::from_bytes`. 1633 /// 2. Encodes chunk body by calling `ChunkBody::data` 1634 /// 3. Checks if the test result is correct. 1635 #[test] ut_chunk_body_encode_0()1636 fn ut_chunk_body_encode_0() { 1637 let content = data_message(); 1638 let mut task = ChunkBody::from_bytes(content.as_slice()); 1639 let mut user_slice = [0_u8; 20]; 1640 let mut output_vec = vec![]; 1641 1642 let mut size = user_slice.len(); 1643 while size == user_slice.len() { 1644 size = task.data(user_slice.as_mut_slice()).unwrap(); 1645 output_vec.extend_from_slice(&user_slice[..size]); 1646 } 1647 assert_eq!(output_vec, res_message()); 1648 } 1649 1650 /// UT test cases for `ChunkBody::data`. 1651 /// 1652 /// # Brief 1653 /// 1. Creates a `ChunkBody` by calling `ChunkBody::from_reader`. 1654 /// 2. Encodes chunk body by calling `ChunkBody::data` 1655 /// 3. Checks if the test result is correct. 1656 #[test] ut_chunk_body_encode_1()1657 fn ut_chunk_body_encode_1() { 1658 let content = data_message(); 1659 let mut task = ChunkBody::from_reader(content.as_slice()); 1660 let mut user_slice = [0_u8; 20]; 1661 let mut output_vec = vec![]; 1662 1663 let mut size = user_slice.len(); 1664 while size == user_slice.len() { 1665 size = task.data(user_slice.as_mut_slice()).unwrap(); 1666 output_vec.extend_from_slice(&user_slice[..size]); 1667 } 1668 assert_eq!(output_vec, res_message()); 1669 } 1670 1671 /// UT test cases for `ChunkBody::data` in async condition. 1672 /// 1673 /// # Brief 1674 /// 1. Creates a `ChunkBody` by calling `ChunkBody::from_bytes`. 1675 /// 2. Encodes chunk body by calling `async_impl::Body::data` 1676 /// 3. Checks if the test result is correct. 1677 #[cfg(feature = "ylong_base")] 1678 #[test] ut_asnyc_chunk_body_encode_0()1679 fn ut_asnyc_chunk_body_encode_0() { 1680 let handle = ylong_runtime::spawn(async move { 1681 asnyc_chunk_body_encode_0().await; 1682 }); 1683 ylong_runtime::block_on(handle).unwrap(); 1684 } 1685 1686 #[cfg(feature = "ylong_base")] asnyc_chunk_body_encode_0()1687 async fn asnyc_chunk_body_encode_0() { 1688 let content = data_message(); 1689 let mut task = ChunkBody::from_bytes(content.as_slice()); 1690 let mut user_slice = [0_u8; 20]; 1691 let mut output_vec = vec![]; 1692 1693 let mut size = user_slice.len(); 1694 while size == user_slice.len() { 1695 size = async_impl::Body::data(&mut task, user_slice.as_mut_slice()) 1696 .await 1697 .unwrap(); 1698 output_vec.extend_from_slice(&user_slice[..size]); 1699 } 1700 assert_eq!(output_vec, res_message()); 1701 } 1702 1703 /// UT test cases for `ChunkBody::data` in async condition. 1704 /// 1705 /// # Brief 1706 /// 1. Creates a `ChunkBody` by calling `ChunkBody::from_async_reader`. 1707 /// 2. Encodes chunk body by calling `async_impl::Body::data` 1708 /// 3. Checks if the test result is correct. 1709 #[cfg(feature = "ylong_base")] 1710 #[test] ut_asnyc_chunk_body_encode_1()1711 fn ut_asnyc_chunk_body_encode_1() { 1712 let handle = ylong_runtime::spawn(async move { 1713 asnyc_chunk_body_encode_1().await; 1714 }); 1715 ylong_runtime::block_on(handle).unwrap(); 1716 } 1717 1718 #[cfg(feature = "ylong_base")] asnyc_chunk_body_encode_1()1719 async fn asnyc_chunk_body_encode_1() { 1720 let content = data_message(); 1721 let mut task = ChunkBody::from_async_reader(content.as_slice()); 1722 let mut user_slice = [0_u8; 1024]; 1723 let mut output_vec = vec![]; 1724 1725 let mut size = user_slice.len(); 1726 while size == user_slice.len() { 1727 size = async_impl::Body::data(&mut task, user_slice.as_mut_slice()) 1728 .await 1729 .unwrap(); 1730 output_vec.extend_from_slice(&user_slice[..size]); 1731 } 1732 assert_eq!(output_vec, res_message()); 1733 } 1734 1735 /// UT test cases for `ChunkBodyDecoder::decode`. 1736 /// 1737 /// # Brief 1738 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 1739 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 1740 /// 3. Checks if the test result is correct. 1741 #[test] ut_chunk_body_decode_0()1742 fn ut_chunk_body_decode_0() { 1743 let mut decoder = ChunkBodyDecoder::new().contains_trailer(true); 1744 let chunk_body_bytes = "\ 1745 5\r\n\ 1746 hello\r\n\ 1747 C ; type = text ;end = !\r\n\ 1748 hello world!\r\n\ 1749 000; message = last\r\n\ 1750 Trailer: value\r\n\ 1751 another-trainer: another-value\r\n\ 1752 \r\n\ 1753 " 1754 .as_bytes(); 1755 // 5 1756 let res = decoder.decode(&chunk_body_bytes[..1]); 1757 let mut chunks = Chunks::new(); 1758 chunks.push(Chunk { 1759 id: 0, 1760 state: ChunkState::MetaSize, 1761 size: 0, 1762 extension: ChunkExt::new(), 1763 data: &[] as &[u8], 1764 trailer: None, 1765 }); 1766 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1767 // 5\r 1768 let res = decoder.decode(&chunk_body_bytes[1..2]); 1769 let mut chunks = Chunks::new(); 1770 chunks.push(Chunk { 1771 id: 0, 1772 state: ChunkState::MetaCrlf, 1773 size: 5, 1774 extension: ChunkExt::new(), 1775 data: &[] as &[u8], 1776 trailer: None, 1777 }); 1778 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1779 // 5\r 1780 let res = decoder.decode(&chunk_body_bytes[2..2]); 1781 let mut chunks = Chunks::new(); 1782 chunks.push(Chunk { 1783 id: 0, 1784 state: ChunkState::MetaCrlf, 1785 size: 5, 1786 extension: ChunkExt::new(), 1787 data: &[] as &[u8], 1788 trailer: None, 1789 }); 1790 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1791 // 5\r\n 1792 let res = decoder.decode(&chunk_body_bytes[2..3]); 1793 let mut chunks = Chunks::new(); 1794 chunks.push(Chunk { 1795 id: 0, 1796 state: ChunkState::Data, 1797 size: 5, 1798 extension: ChunkExt::new(), 1799 data: &[] as &[u8], 1800 trailer: None, 1801 }); 1802 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1803 1804 // 5\r\nhe 1805 let res = decoder.decode(&chunk_body_bytes[3..5]); 1806 let mut chunks = Chunks::new(); 1807 chunks.push(Chunk { 1808 id: 0, 1809 state: ChunkState::Data, 1810 size: 5, 1811 extension: ChunkExt::new(), 1812 data: "he".as_bytes(), 1813 trailer: None, 1814 }); 1815 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1816 1817 // 5\r\nhello\r 1818 let res = decoder.decode(&chunk_body_bytes[5..9]); 1819 let mut chunks = Chunks::new(); 1820 chunks.push(Chunk { 1821 id: 0, 1822 state: ChunkState::DataCrlf, 1823 size: 5, 1824 extension: ChunkExt::new(), 1825 data: "llo".as_bytes(), 1826 trailer: None, 1827 }); 1828 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1829 1830 // 5\r\nhello\r 1831 let res = decoder.decode(&chunk_body_bytes[9..9]); 1832 let mut chunks = Chunks::new(); 1833 chunks.push(Chunk { 1834 id: 0, 1835 state: ChunkState::DataCrlf, 1836 size: 5, 1837 extension: ChunkExt::new(), 1838 data: &[] as &[u8], 1839 trailer: None, 1840 }); 1841 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1842 1843 // 5\r\nhello\r\n 1844 let res = decoder.decode(&chunk_body_bytes[9..10]); 1845 let mut chunks = Chunks::new(); 1846 chunks.push(Chunk { 1847 id: 0, 1848 state: ChunkState::Finish, 1849 size: 5, 1850 extension: ChunkExt::new(), 1851 data: &[] as &[u8], 1852 trailer: None, 1853 }); 1854 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1855 1856 // 5\r\nhello\r\nC ; 1857 let res = decoder.decode(&chunk_body_bytes[10..13]); 1858 let mut chunks = Chunks::new(); 1859 chunks.push(Chunk { 1860 id: 1, 1861 state: ChunkState::MetaExt, 1862 size: 12, 1863 extension: ChunkExt::new(), 1864 data: &[] as &[u8], 1865 trailer: None, 1866 }); 1867 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1868 1869 // 5\r\nhello\r\nC ; type = text ; 1870 let res = decoder.decode(&chunk_body_bytes[13..27]); 1871 let mut chunks = Chunks::new(); 1872 chunks.push(Chunk { 1873 id: 1, 1874 state: ChunkState::MetaExt, 1875 size: 12, 1876 extension: ChunkExt::new(), 1877 data: &[] as &[u8], 1878 trailer: None, 1879 }); 1880 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1881 1882 // 5\r\nhello\r\nC ; type = text ;end = !\r\n 1883 let res = decoder.decode(&chunk_body_bytes[27..36]); 1884 let mut chunks = Chunks::new(); 1885 chunks.push(Chunk { 1886 id: 1, 1887 state: ChunkState::Data, 1888 size: 12, 1889 extension: ChunkExt::new(), 1890 data: &[] as &[u8], 1891 trailer: None, 1892 }); 1893 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1894 1895 // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n 1896 let res = decoder.decode(&chunk_body_bytes[36..50]); 1897 let mut chunks = Chunks::new(); 1898 chunks.push(Chunk { 1899 id: 1, 1900 state: ChunkState::Finish, 1901 size: 12, 1902 extension: ChunkExt::new(), 1903 data: "hello world!".as_bytes(), 1904 trailer: None, 1905 }); 1906 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1907 1908 // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n0 1909 let res = decoder.decode(&chunk_body_bytes[50..51]); 1910 let mut chunks = Chunks::new(); 1911 chunks.push(Chunk { 1912 id: 2, 1913 state: ChunkState::MetaSize, 1914 size: 0, 1915 extension: ChunkExt::new(), 1916 data: &[] as &[u8], 1917 trailer: None, 1918 }); 1919 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1920 1921 // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; 1922 let res = decoder.decode(&chunk_body_bytes[51..54]); 1923 let mut chunks = Chunks::new(); 1924 chunks.push(Chunk { 1925 id: 2, 1926 state: ChunkState::MetaExt, 1927 size: 0, 1928 extension: ChunkExt::new(), 1929 data: &[] as &[u8], 1930 trailer: Some(&[] as &[u8]), 1931 }); 1932 assert_eq!(res, Ok((chunks, &[] as &[u8],))); 1933 1934 // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = 1935 // last\r\n 1936 let res = decoder.decode(&chunk_body_bytes[54..71]); 1937 let mut chunks = Chunks::new(); 1938 chunks.push(Chunk { 1939 id: 2, 1940 state: ChunkState::Data, 1941 size: 0, 1942 extension: ChunkExt::new(), 1943 data: &[] as &[u8], 1944 trailer: Some(&[] as &[u8]), 1945 }); 1946 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 1947 // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = 1948 // last\r\nTrailer: value\r\n 1949 let res = decoder.decode(&chunk_body_bytes[71..87]); 1950 let mut chunks = Chunks::new(); 1951 chunks.push(Chunk { 1952 id: 3, 1953 state: ChunkState::DataCrlf, 1954 size: 0, 1955 extension: ChunkExt::new(), 1956 data: &[] as &[u8], 1957 trailer: Some("Trailer: value".as_bytes()), 1958 }); 1959 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 1960 // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; 1961 // message = last\r\nTrailer: value\r\n\another-trainer: another-value\r\n\ 1962 let res = decoder.decode(&chunk_body_bytes[87..119]); 1963 let mut chunks = Chunks::new(); 1964 chunks.push(Chunk { 1965 id: 4, 1966 state: ChunkState::DataCrlf, 1967 size: 0, 1968 extension: ChunkExt::new(), 1969 data: &[] as &[u8], 1970 trailer: Some("another-trainer: another-value".as_bytes()), 1971 }); 1972 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 1973 // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; 1974 // message = last\r\nTrailer: value\r\n\another-trainer: another-value\r\n\r\n\ 1975 let res = decoder.decode(&chunk_body_bytes[119..121]); 1976 let mut chunks = Chunks::new(); 1977 chunks.push(Chunk { 1978 id: 5, 1979 state: ChunkState::Finish, 1980 size: 0, 1981 extension: ChunkExt::new(), 1982 data: &[] as &[u8], 1983 trailer: Some(&[] as &[u8]), 1984 }); 1985 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 1986 } 1987 1988 /// UT test cases for `ChunkBodyDecoder::decode`. 1989 /// 1990 /// # Brief 1991 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 1992 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 1993 /// 3. Checks if the test result is correct. 1994 #[test] ut_chunk_body_decode_1()1995 fn ut_chunk_body_decode_1() { 1996 let mut decoder = ChunkBodyDecoder::new(); 1997 let chunk_body_bytes = "\ 1998 5\r\n\ 1999 hello\r\n\ 2000 C ; type = text ;end = !\r\n\ 2001 hello world!\r\n\ 2002 000; message = last\r\n\ 2003 \r\n\ 2004 " 2005 .as_bytes(); 2006 2007 // 5 2008 let (chunks, remaining) = decoder.decode(chunk_body_bytes).unwrap(); 2009 let mut iter = chunks.iter(); 2010 let chunk = Chunk { 2011 id: 0, 2012 state: ChunkState::Finish, 2013 size: 5, 2014 extension: ChunkExt::new(), 2015 data: "hello".as_bytes(), 2016 trailer: None, 2017 }; 2018 assert_eq!(iter.next(), Some(&chunk)); 2019 let chunk = Chunk { 2020 id: 1, 2021 state: ChunkState::Finish, 2022 size: 12, 2023 extension: ChunkExt::new(), 2024 data: "hello world!".as_bytes(), 2025 trailer: None, 2026 }; 2027 assert_eq!(iter.next(), Some(&chunk)); 2028 let chunk = Chunk { 2029 id: 2, 2030 state: ChunkState::Finish, 2031 size: 0, 2032 extension: ChunkExt::new(), 2033 data: &[] as &[u8], 2034 trailer: None, 2035 }; 2036 assert_eq!(iter.next(), Some(&chunk)); 2037 assert_eq!(iter.next(), None); 2038 assert_eq!(remaining, "".as_bytes()); 2039 } 2040 2041 /// UT test cases for `ChunkBodyDecoder::decode`. 2042 /// 2043 /// # Brief 2044 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 2045 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 2046 /// 3. Checks if the test result is correct. 2047 #[test] ut_chunk_body_decode_2()2048 fn ut_chunk_body_decode_2() { 2049 let mut decoder = ChunkBodyDecoder::new(); 2050 let chunk_body_bytes = "\ 2051 5\r\n\ 2052 hello\r\n\ 2053 C ; type = text ;end = !\r\n\ 2054 hello world!\r\n\ 2055 000; message = last\r\n\ 2056 \r\n\ 2057 " 2058 .as_bytes(); 2059 2060 // 5 2061 let (chunks, remaining) = decoder.decode(chunk_body_bytes).unwrap(); 2062 let mut iter = chunks.into_iter(); 2063 let chunk = Chunk { 2064 id: 0, 2065 state: ChunkState::Finish, 2066 size: 5, 2067 extension: ChunkExt::new(), 2068 data: "hello".as_bytes(), 2069 trailer: None, 2070 }; 2071 assert_eq!(iter.next(), Some(chunk)); 2072 let chunk = Chunk { 2073 id: 1, 2074 state: ChunkState::Finish, 2075 size: 12, 2076 extension: ChunkExt::new(), 2077 data: "hello world!".as_bytes(), 2078 trailer: None, 2079 }; 2080 assert_eq!(iter.next(), Some(chunk)); 2081 let chunk = Chunk { 2082 id: 2, 2083 state: ChunkState::Finish, 2084 size: 0, 2085 extension: ChunkExt::new(), 2086 data: &[] as &[u8], 2087 trailer: None, 2088 }; 2089 assert_eq!(iter.next(), Some(chunk)); 2090 assert_eq!(iter.next(), None); 2091 assert_eq!(remaining, "".as_bytes()); 2092 } 2093 2094 /// UT test cases for `ChunkBodyDecoder::decode`. 2095 /// 2096 /// # Brief 2097 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 2098 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 2099 /// 3. Checks if the test result is correct. 2100 #[test] ut_chunk_body_decode_3()2101 fn ut_chunk_body_decode_3() { 2102 let chunk_body_bytes = "\ 2103 5 ; type = text ;end = !\r\n\ 2104 hello world!\r\n\ 2105 000; message = last\r\n\ 2106 \r\n\ 2107 " 2108 .as_bytes(); 2109 let mut decoder = ChunkBodyDecoder::new(); 2110 2111 // 5 2112 let res = decoder.decode(chunk_body_bytes); 2113 assert_eq!(res, Err(ErrorKind::InvalidInput.into())); 2114 } 2115 2116 /// UT test cases for `ChunkBodyDecoder::decode`. 2117 /// 2118 /// # Brief 2119 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 2120 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 2121 /// 3. Checks if the test result is correct. 2122 #[test] ut_chunk_body_decode_4()2123 fn ut_chunk_body_decode_4() { 2124 let chunk_body_bytes = "\ 2125 C ; type = text ;end = !\r\r\n\ 2126 hello world!\r\n\ 2127 000; message = last\r\n\ 2128 Trailer: value\r\n\ 2129 another-trainer: another-value\r\n\ 2130 \r\n\ 2131 " 2132 .as_bytes(); 2133 let mut decoder = ChunkBodyDecoder::new(); 2134 2135 // 5 2136 let res = decoder.decode(chunk_body_bytes); 2137 assert_eq!(res, Err(ErrorKind::InvalidInput.into())); 2138 } 2139 2140 /// UT test cases for `ChunkBodyDecoder::decode`. 2141 /// 2142 /// # Brief 2143 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 2144 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 2145 /// 3. Checks if the test result is correct. 2146 #[test] ut_chunk_body_decode_5()2147 fn ut_chunk_body_decode_5() { 2148 let chunk_body_bytes = " C ; type = text ;end = !\r\n\ 2149 hello world!\r\n\ 2150 000; message = last\r\n\ 2151 Trailer: value\r\n\ 2152 another-trainer: another-value\r\n\ 2153 \r\n\ 2154 " 2155 .as_bytes(); 2156 let mut decoder = ChunkBodyDecoder::new(); 2157 // 5 2158 let res = decoder.decode(chunk_body_bytes); 2159 assert_eq!(res, Err(ErrorKind::InvalidInput.into())); 2160 } 2161 2162 /// UT test cases for `ChunkBodyDecoder::decode`. 2163 /// 2164 /// # Brief 2165 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 2166 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 2167 /// 3. Checks if the test result is correct. 2168 #[test] ut_chunk_body_decode_6()2169 fn ut_chunk_body_decode_6() { 2170 let mut decoder = ChunkBodyDecoder::new(); 2171 let chunk_body_bytes = "\ 2172 5\r\n\ 2173 hello\r\n\ 2174 C ; type = text ;end = !\r\n\ 2175 hello world!\r\n\ 2176 000; message = last\r\n\ 2177 \r\n\ 2178 " 2179 .as_bytes(); 2180 2181 // 5 2182 let (chunks, _) = decoder.decode(chunk_body_bytes).unwrap(); 2183 assert_eq!(chunks.iter().len(), 3); 2184 let chunk = chunks.iter().next().unwrap(); 2185 assert_eq!( 2186 ( 2187 chunk.id(), 2188 chunk.state(), 2189 chunk.size(), 2190 chunk.extension(), 2191 chunk.data() 2192 ), 2193 ( 2194 0, 2195 &ChunkState::Finish, 2196 5, 2197 &ChunkExt::new(), 2198 "hello".as_bytes() 2199 ) 2200 ); 2201 } 2202 2203 /// UT test cases for `ChunkBodyDecoder::decode`. 2204 /// 2205 /// # Brief 2206 /// 1. Creates a `ChunkBodyDecoder` by calling `ChunkBodyDecoder::new`. 2207 /// 2. Decodes chunk body by calling `ChunkBodyDecoder::decode` 2208 /// 3. Checks if the test result is correct. 2209 #[test] ut_chunk_body_decode_7()2210 fn ut_chunk_body_decode_7() { 2211 let mut decoder = ChunkBodyDecoder::new().contains_trailer(true); 2212 let buf = b"010\r\nAAAAAAAAAAAAAAAA\r\n0\r\ntrailer:value\r\n\r\n"; 2213 let res = decoder.decode(&buf[0..23]); // 010\r\nAAAAAAAAAAAAAAAA\r\n 2214 let mut chunks = Chunks::new(); 2215 chunks.push(Chunk { 2216 id: 0, 2217 state: ChunkState::Finish, 2218 size: 16, 2219 extension: ChunkExt::new(), 2220 data: "AAAAAAAAAAAAAAAA".as_bytes(), 2221 trailer: None, 2222 }); 2223 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 2224 2225 let res = decoder.decode(&buf[23..39]); // 0\r\ntrailer:value 2226 let mut chunks = Chunks::new(); 2227 chunks.push(Chunk { 2228 id: 1, 2229 state: ChunkState::Data, 2230 size: 0, 2231 extension: ChunkExt::new(), 2232 data: &[] as &[u8], 2233 trailer: Some("trailer:value".as_bytes()), 2234 }); 2235 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 2236 2237 let res = decoder.decode(&buf[39..41]); //\r\n 2238 let mut chunks = Chunks::new(); 2239 chunks.push(Chunk { 2240 id: 2, 2241 state: ChunkState::DataCrlf, 2242 size: 0, 2243 extension: ChunkExt::new(), 2244 data: &[] as &[u8], 2245 trailer: Some(&[] as &[u8]), 2246 }); 2247 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 2248 2249 let res = decoder.decode(&buf[41..]); //\r\n 2250 let mut chunks = Chunks::new(); 2251 chunks.push(Chunk { 2252 id: 3, 2253 state: ChunkState::Finish, 2254 size: 0, 2255 extension: ChunkExt::new(), 2256 data: &[] as &[u8], 2257 trailer: Some(&[] as &[u8]), 2258 }); 2259 assert_eq!(res, Ok((chunks, &[] as &[u8]))); 2260 2261 let trailer_headers = decoder.get_trailer().unwrap().unwrap(); 2262 let value = trailer_headers.get("trailer"); 2263 assert_eq!(value.unwrap().to_str().unwrap(), "value"); 2264 } 2265 } 2266