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 std::convert::TryFrom; 15 16 use crate::error::HttpError; 17 use crate::h2::{ErrorCode, H2Error, Parts, PseudoHeaders}; 18 use crate::headers; 19 20 /// Mask for the END_STREAM flag. 21 /// When set, indicates that the sender will not send further frames for this 22 /// stream. 23 pub(crate) const END_STREAM_MASK: u8 = 0x01; 24 25 /// Mask for the RST_STREAM flag. 26 /// When set, indicates that the stream is being terminated. 27 pub(crate) const RST_STREAM_MASK: u8 = 0x03; 28 29 /// Mask for the END_HEADERS flag. 30 /// When set, indicates that this frame contains an entire header block and not 31 /// a fragment. 32 pub(crate) const END_HEADERS_MASK: u8 = 0x04; 33 34 /// Mask for the PADDED flag. 35 /// When set, indicates that the frame payload is followed by a padding field. 36 pub(crate) const PADDED_MASK: u8 = 0x08; 37 38 /// Mask for the HEADERS_PRIORITY flag. 39 /// When set, indicates that the headers frame also contains the priority 40 /// information. 41 pub(crate) const HEADERS_PRIORITY_MASK: u8 = 0x20; 42 43 /// Mask for the ACK flag 44 pub(crate) const ACK_MASK: u8 = 0x1; 45 46 /// HTTP/2 frame structure, including the stream ID, flags, and payload 47 /// information. The frame type information is represented by the `Payload` 48 /// type. This structure represents the fundamental unit of communication in 49 /// HTTP/2. 50 #[derive(Clone)] 51 pub struct Frame { 52 id: StreamId, 53 flags: FrameFlags, 54 payload: Payload, 55 } 56 57 /// Enum representing the type of HTTP/2 frame. 58 /// Each HTTP/2 frame type serves a unique role in the communication process. 59 #[derive(PartialEq, Eq, Debug)] 60 pub enum FrameType { 61 Data = 0x0, 62 Headers = 0x1, 63 Priority = 0x2, 64 RstStream = 0x03, 65 Settings = 0x4, 66 PushPromise = 0x5, 67 Ping = 0x6, 68 Goaway = 0x7, 69 WindowUpdate = 0x8, 70 Continuation = 0x9, 71 // add more frame types as needed 72 } 73 74 /// Enum representing the payload of an HTTP/2 frame. 75 /// The payload differs based on the type of frame. 76 #[derive(Clone)] 77 pub enum Payload { 78 /// HEADERS frame payload. 79 Headers(Headers), 80 /// DATA frame payload. 81 Data(Data), 82 /// PRIORITY frame payload. 83 Priority(Priority), 84 /// RST_STREAM frame payload. 85 RstStream(RstStream), 86 /// PING frame payload. 87 Ping(Ping), 88 /// SETTINGS frame payload. 89 Settings(Settings), 90 /// GOAWAY frame payload. 91 Goaway(Goaway), 92 /// WINDOW_UPDATE frame payload. 93 WindowUpdate(WindowUpdate), 94 /// PUSH_PROMISE 95 PushPromise(PushPromise), 96 } 97 98 /// Enum representing the different settings that can be included in a SETTINGS 99 /// frame. Each setting has a different role in the HTTP/2 communication 100 /// process. 101 #[derive(Clone, PartialEq, Eq, Debug)] 102 pub enum Setting { 103 /// SETTINGS_HEADER_TABLE_SIZE 104 HeaderTableSize(u32), 105 /// SETTINGS_ENABLE_PUSH 106 EnablePush(bool), 107 /// SETTINGS_MAX_CONCURRENT_STREAMS 108 MaxConcurrentStreams(u32), 109 /// SETTINGS_INITIAL_WINDOW_SIZE 110 InitialWindowSize(u32), 111 /// SETTINGS_MAX_FRAME_SIZE 112 MaxFrameSize(u32), 113 /// SETTINGS_MAX_HEADER_LIST_SIZE 114 MaxHeaderListSize(u32), 115 } 116 117 type StreamId = usize; 118 119 /// HTTP/2 frame flags. 120 #[derive(Clone)] 121 pub struct FrameFlags(u8); 122 123 /// HTTP/2 HEADERS frame's payload, contains pseudo headers and other headers. 124 #[derive(Clone)] 125 pub struct Headers { 126 parts: Parts, 127 } 128 129 /// HTTP/2 DATA frame's payload, contains all content after padding is removed. 130 /// The DATA frame defines the payload data of an HTTP/2 request or response. 131 #[derive(Clone)] 132 pub struct Data { 133 data: Vec<u8>, 134 } 135 136 /// Represents the PRIORITY frame payload. 137 /// The PRIORITY frame specifies the sender-advised priority of a stream. 138 #[derive(Clone)] 139 pub struct Priority { 140 exclusive: bool, 141 stream_dependency: u32, 142 weight: u8, 143 } 144 145 /// The RST_STREAM frame allows for immediate termination of a stream. 146 /// RST_STREAM is sent to request cancellation of a stream or to indicate an 147 /// error situation. 148 #[derive(Clone)] 149 pub struct RstStream { 150 error_code: u32, 151 } 152 153 /// Represents the PING frame payload. 154 /// The PING frame is a mechanism for measuring a minimal round-trip time from 155 /// the sender. 156 #[derive(Clone)] 157 pub struct Ping { 158 /// The opaque data of PING 159 pub data: [u8; 8], 160 } 161 162 /// Represents the SETTINGS frame payload. 163 /// The SETTINGS frame conveys configuration parameters that affect how 164 /// endpoints communicate. 165 #[derive(Clone)] 166 pub struct Settings { 167 settings: Vec<Setting>, 168 } 169 170 /// Represents the GOAWAY frame payload. 171 /// The GOAWAY frame is used to initiate shutdown of a connection or to signal 172 /// serious error conditions. 173 #[derive(Clone)] 174 pub struct Goaway { 175 error_code: u32, 176 last_stream_id: StreamId, 177 debug_data: Vec<u8>, 178 } 179 180 /// Represents the WINDOW_UPDATE frame payload. 181 /// The WINDOW_UPDATE frame is used to implement flow control in HTTP/2. 182 #[derive(Clone)] 183 pub struct WindowUpdate { 184 window_size_increment: u32, 185 } 186 187 /// Represents the PUSH_PROMISE frame payload. 188 /// The PUSH_PROMISE frame is used to notify the peer endpoint in advance of 189 /// streams the sender intends to initiate. 190 #[derive(Clone)] 191 pub struct PushPromise { 192 promised_stream_id: u32, 193 parts: Parts, 194 } 195 196 /// A Builder of SETTINGS payload. 197 pub struct SettingsBuilder { 198 settings: Vec<Setting>, 199 } 200 201 impl Frame { 202 /// Returns the stream identifier (`StreamId`) of the frame. stream_id(&self) -> StreamId203 pub fn stream_id(&self) -> StreamId { 204 self.id 205 } 206 207 /// Constructs a new `Frame` with the given `StreamId`, `FrameFlags`, 208 /// `Payload`. new(id: StreamId, flags: FrameFlags, payload: Payload) -> Self209 pub fn new(id: StreamId, flags: FrameFlags, payload: Payload) -> Self { 210 Frame { id, flags, payload } 211 } 212 213 /// Returns a reference to the frame's flags (`FrameFlags`). flags(&self) -> &FrameFlags214 pub fn flags(&self) -> &FrameFlags { 215 &self.flags 216 } 217 218 /// Returns a reference to the frame's payload (`Payload`). payload(&self) -> &Payload219 pub fn payload(&self) -> &Payload { 220 &self.payload 221 } 222 223 /// Returns a mutable reference to the frame's payload (`Payload`). 224 /// This can be used to modify the payload of the frame. payload_mut(&mut self) -> &mut Payload225 pub(crate) fn payload_mut(&mut self) -> &mut Payload { 226 &mut self.payload 227 } 228 } 229 230 impl FrameFlags { 231 /// Creates a new `FrameFlags` instance with the given `flags` byte. new(flags: u8) -> Self232 pub fn new(flags: u8) -> Self { 233 FrameFlags(flags) 234 } 235 236 /// Creates a new `FrameFlags` instance with no flags set. empty() -> Self237 pub fn empty() -> Self { 238 FrameFlags(0) 239 } 240 241 /// Judges the END_FLOW Flag is true. is_end_stream(&self) -> bool242 pub fn is_end_stream(&self) -> bool { 243 self.0 & END_STREAM_MASK == END_STREAM_MASK 244 } 245 246 /// Judges the END_HEADERS Flag is true. is_end_headers(&self) -> bool247 pub fn is_end_headers(&self) -> bool { 248 self.0 & END_HEADERS_MASK == END_HEADERS_MASK 249 } 250 251 /// Judges the PADDED Flag is true. is_padded(&self) -> bool252 pub fn is_padded(&self) -> bool { 253 self.0 & PADDED_MASK == PADDED_MASK 254 } 255 256 /// Judge the ACK flag is true. is_ack(&self) -> bool257 pub fn is_ack(&self) -> bool { 258 self.0 & ACK_MASK == ACK_MASK 259 } 260 261 /// Get Flags octet. bits(&self) -> u8262 pub fn bits(&self) -> u8 { 263 self.0 264 } 265 266 /// Sets the END_STREAM flag. set_end_stream(&mut self, end_stream: bool)267 pub fn set_end_stream(&mut self, end_stream: bool) { 268 if end_stream { 269 self.0 |= END_STREAM_MASK; 270 } else { 271 self.0 &= !END_STREAM_MASK; 272 } 273 } 274 275 /// Sets the END_HEADERS flag. set_end_headers(&mut self, end_headers: bool)276 pub fn set_end_headers(&mut self, end_headers: bool) { 277 if end_headers { 278 self.0 |= END_HEADERS_MASK; 279 } else { 280 self.0 &= !END_HEADERS_MASK; 281 } 282 } 283 284 /// Sets the PADDED flag. set_padded(&mut self, padded: bool)285 pub fn set_padded(&mut self, padded: bool) { 286 if padded { 287 self.0 |= PADDED_MASK; 288 } else { 289 self.0 &= !PADDED_MASK; 290 } 291 } 292 } 293 294 impl Payload { 295 /// Returns a reference to the Headers if the Payload is of the Headers 296 /// variant. If the Payload is not of the Headers variant, returns None. as_headers(&self) -> Option<&Headers>297 pub(crate) fn as_headers(&self) -> Option<&Headers> { 298 if let Payload::Headers(headers) = self { 299 Some(headers) 300 } else { 301 None 302 } 303 } 304 305 /// Returns the type of the frame (`FrameType`) that this payload would be 306 /// associated with. The returned `FrameType` is determined based on the 307 /// variant of the Payload. frame_type(&self) -> FrameType308 pub fn frame_type(&self) -> FrameType { 309 match self { 310 Payload::Headers(_) => FrameType::Headers, 311 Payload::Data(_) => FrameType::Data, 312 Payload::Priority(_) => FrameType::Priority, 313 Payload::Ping(_) => FrameType::Ping, 314 Payload::RstStream(_) => FrameType::RstStream, 315 Payload::Settings(_) => FrameType::Settings, 316 Payload::Goaway(_) => FrameType::Goaway, 317 Payload::WindowUpdate(_) => FrameType::WindowUpdate, 318 Payload::PushPromise(_) => FrameType::PushPromise, 319 } 320 } 321 } 322 323 impl Headers { 324 /// Creates a new Headers instance from the provided Parts. new(parts: Parts) -> Self325 pub fn new(parts: Parts) -> Self { 326 Headers { parts } 327 } 328 329 /// Returns pseudo headers and other headers as tuples. parts(&self) -> (&PseudoHeaders, &headers::Headers)330 pub fn parts(&self) -> (&PseudoHeaders, &headers::Headers) { 331 self.parts.parts() 332 } 333 334 /// Returns a copy of the internal parts of the Headers. get_parts(&self) -> Parts335 pub(crate) fn get_parts(&self) -> Parts { 336 self.parts.clone() 337 } 338 } 339 340 impl Data { 341 /// Creates a new Data instance containing the provided data. new(data: Vec<u8>) -> Self342 pub fn new(data: Vec<u8>) -> Self { 343 Data { data } 344 } 345 346 /// Return the `Vec` that contains the data payload. data(&self) -> &Vec<u8>347 pub fn data(&self) -> &Vec<u8> { 348 &self.data 349 } 350 } 351 352 impl Settings { 353 /// Creates a new Settings instance containing the provided settings. new(settings: Vec<Setting>) -> Self354 pub fn new(settings: Vec<Setting>) -> Self { 355 Settings { settings } 356 } 357 358 /// Returns a slice of the settings. get_settings(&self) -> &[Setting]359 pub fn get_settings(&self) -> &[Setting] { 360 &self.settings 361 } 362 363 /// Adds or updates a setting. update_setting(&mut self, setting: Setting)364 pub(crate) fn update_setting(&mut self, setting: Setting) { 365 let setting_id = setting.setting_identifier(); 366 if let Some(existing_setting) = self 367 .settings 368 .iter_mut() 369 .find(|s| s.setting_identifier() == setting_id) 370 { 371 *existing_setting = setting; 372 } else { 373 self.settings.push(setting); 374 } 375 } 376 377 /// Returns the total length of the settings when encoded. encoded_len(&self) -> usize378 pub fn encoded_len(&self) -> usize { 379 let settings_count = self.settings.len(); 380 // Each setting has a 2-byte ID and a 4-byte value 381 let setting_size = 6; 382 settings_count * setting_size 383 } 384 } 385 386 impl Setting { 387 /// Returns the identifier associated with the setting. setting_identifier(&self) -> u16388 pub fn setting_identifier(&self) -> u16 { 389 match self { 390 Setting::HeaderTableSize(_) => 0x01, 391 Setting::EnablePush(_) => 0x02, 392 Setting::MaxConcurrentStreams(_) => 0x03, 393 Setting::InitialWindowSize(_) => 0x04, 394 Setting::MaxFrameSize(_) => 0x05, 395 Setting::MaxHeaderListSize(_) => 0x06, 396 } 397 } 398 } 399 400 impl SettingsBuilder { 401 /// `SettingsBuilder` constructor. new() -> Self402 pub fn new() -> Self { 403 SettingsBuilder { settings: vec![] } 404 } 405 406 /// SETTINGS_HEADER_TABLE_SIZE (0x01) setting. header_table_size(mut self, size: u32) -> Self407 pub fn header_table_size(mut self, size: u32) -> Self { 408 self.settings.push(Setting::HeaderTableSize(size)); 409 self 410 } 411 412 /// SETTINGS_ENABLE_PUSH (0x02) setting. enable_push(mut self, is_enable: bool) -> Self413 pub fn enable_push(mut self, is_enable: bool) -> Self { 414 self.settings.push(Setting::EnablePush(is_enable)); 415 self 416 } 417 418 /// SETTINGS_MAX_FRAME_SIZE (0x05) setting. max_frame_size(mut self, size: u32) -> Self419 pub fn max_frame_size(mut self, size: u32) -> Self { 420 self.settings.push(Setting::MaxFrameSize(size)); 421 self 422 } 423 424 /// SETTINGS_MAX_HEADER_LIST_SIZE (0x06) setting. max_header_list_size(mut self, size: u32) -> Self425 pub fn max_header_list_size(mut self, size: u32) -> Self { 426 self.settings.push(Setting::MaxHeaderListSize(size)); 427 self 428 } 429 430 /// Consumes the Builder and constructs a SETTINGS payload. 431 /// 432 /// # Examples 433 /// 434 /// ``` 435 /// use ylong_http::h2::SettingsBuilder; 436 /// 437 /// let settings = SettingsBuilder::new() 438 /// .enable_push(true) 439 /// .header_table_size(4096) 440 /// .max_frame_size(2 << 13) 441 /// .build(); 442 /// ``` build(self) -> Settings443 pub fn build(self) -> Settings { 444 Settings::new(self.settings) 445 } 446 } 447 448 impl Default for SettingsBuilder { default() -> Self449 fn default() -> Self { 450 Self::new() 451 } 452 } 453 454 impl Goaway { 455 /// Creates a new Goaway instance with the provided error code, last stream 456 /// ID, and debug data. new(error_code: u32, last_stream_id: StreamId, debug_data: Vec<u8>) -> Self457 pub fn new(error_code: u32, last_stream_id: StreamId, debug_data: Vec<u8>) -> Self { 458 Goaway { 459 error_code, 460 last_stream_id, 461 debug_data, 462 } 463 } 464 465 /// Returns a slice of the debug data. get_debug_data(&self) -> &[u8]466 pub fn get_debug_data(&self) -> &[u8] { 467 &self.debug_data 468 } 469 470 /// Returns the identifier of the last stream processed by the sender. get_last_stream_id(&self) -> StreamId471 pub fn get_last_stream_id(&self) -> StreamId { 472 self.last_stream_id 473 } 474 475 /// Returns the error code. get_error_code(&self) -> u32476 pub fn get_error_code(&self) -> u32 { 477 self.error_code 478 } 479 480 /// Returns the total length of the Goaway frame when encoded. encoded_len(&self) -> usize481 pub fn encoded_len(&self) -> usize { 482 8 + self.debug_data.len() // 4-byte Last-Stream-ID + 4-byte Error Code + 483 // Debug Data length 484 } 485 } 486 487 impl WindowUpdate { 488 /// Creates a new WindowUpdate instance with the provided window size 489 /// increment. new(window_size_increment: u32) -> Self490 pub fn new(window_size_increment: u32) -> Self { 491 WindowUpdate { 492 window_size_increment, 493 } 494 } 495 496 /// Returns the window size increment. get_increment(&self) -> u32497 pub(crate) fn get_increment(&self) -> u32 { 498 self.window_size_increment 499 } 500 501 /// Returns the length of the WindowUpdate frame when encoded. encoded_len(&self) -> usize502 pub fn encoded_len(&self) -> usize { 503 4 // 4-byte window size increment 504 } 505 } 506 507 impl Priority { 508 /// Creates a new Priority instance with the provided exclusive flag, stream 509 /// dependency, and weight. new(exclusive: bool, stream_dependency: u32, weight: u8) -> Self510 pub fn new(exclusive: bool, stream_dependency: u32, weight: u8) -> Self { 511 Priority { 512 exclusive, 513 stream_dependency, 514 weight, 515 } 516 } 517 518 /// Returns whether the stream is exclusive. get_exclusive(&self) -> bool519 pub fn get_exclusive(&self) -> bool { 520 self.exclusive 521 } 522 523 /// Returns the stream dependency. get_stream_dependency(&self) -> u32524 pub fn get_stream_dependency(&self) -> u32 { 525 self.stream_dependency 526 } 527 528 /// Returns the weight of the stream. get_weight(&self) -> u8529 pub fn get_weight(&self) -> u8 { 530 self.weight 531 } 532 } 533 534 impl RstStream { 535 /// Creates a new RstStream instance with the provided error code. new(error_code: u32) -> Self536 pub fn new(error_code: u32) -> Self { 537 Self { error_code } 538 } 539 540 /// Returns the error code associated with the RstStream. error_code(&self) -> u32541 pub fn error_code(&self) -> u32 { 542 self.error_code 543 } 544 545 /// GET the `ErrorCode` of `RstStream` error(&self, id: u32) -> Result<H2Error, HttpError>546 pub fn error(&self, id: u32) -> Result<H2Error, HttpError> { 547 Ok(H2Error::StreamError( 548 id, 549 ErrorCode::try_from(self.error_code)?, 550 )) 551 } 552 } 553 554 impl Ping { 555 /// Creates a new Ping instance with the provided data. new(data: [u8; 8]) -> Self556 pub fn new(data: [u8; 8]) -> Self { 557 Ping { data } 558 } 559 560 /// Returns the data associated with the Ping. data(&self) -> [u8; 8]561 pub fn data(&self) -> [u8; 8] { 562 self.data 563 } 564 } 565 566 impl PushPromise { 567 /// `PushPromise` constructor. new(promised_stream_id: u32, parts: Parts) -> Self568 pub fn new(promised_stream_id: u32, parts: Parts) -> Self { 569 Self { 570 promised_stream_id, 571 parts, 572 } 573 } 574 } 575 576 #[cfg(test)] 577 mod ut_frame { 578 use super::*; 579 use crate::h2::Parts; 580 581 /// UT test cases for `SettingsBuilder`. 582 /// 583 /// # Brief 584 /// 1. Creates a `SettingsBuilder`. 585 /// 2. Sets various setting parameters using builder methods. 586 /// 3. Builds a `Settings` object. 587 /// 4. Gets a reference to the underlying `Vec<Setting>` from the `Settings` 588 /// object. 589 /// 5. Iterates over each setting in the `Vec<Setting>` and checks whether 590 /// it matches the expected value. 591 #[test] ut_settings_builder()592 fn ut_settings_builder() { 593 let settings = SettingsBuilder::new() 594 .header_table_size(4096) 595 .enable_push(true) 596 .max_frame_size(16384) 597 .max_header_list_size(8192) 598 .build(); 599 600 let mut setting_iter = settings.get_settings().iter(); 601 // Check that the first setting is as expected 602 assert_eq!(setting_iter.next(), Some(&Setting::HeaderTableSize(4096))); 603 // Check that the second setting is as expected 604 assert_eq!(setting_iter.next(), Some(&Setting::EnablePush(true))); 605 // Check that the third setting is as expected 606 assert_eq!(setting_iter.next(), Some(&Setting::MaxFrameSize(16384))); 607 // Check that the fourth setting is as expected 608 assert_eq!(setting_iter.next(), Some(&Setting::MaxHeaderListSize(8192))); 609 // Check that there are no more settings 610 assert_eq!(setting_iter.next(), None); 611 } 612 613 /// UT test cases for `Ping`. 614 /// 615 /// # Brief 616 /// 1. Creates a `Ping` instance with specific data. 617 /// 2. Checks if the data of the `Ping` instance is correct. 618 #[test] ut_ping()619 fn ut_ping() { 620 let data = [1, 2, 3, 4, 5, 6, 7, 8]; 621 let ping = Ping::new(data); 622 assert_eq!(ping.data(), data); 623 } 624 625 /// UT test cases for `Setting`. 626 /// 627 /// # Brief 628 /// 1. Creates a `Setting` instance for each possible variant with a 629 /// specific value. 630 /// 2. Checks if the identifier of the `Setting` instance is correct. 631 #[test] ut_setting()632 fn ut_setting() { 633 let setting_header_table_size = Setting::HeaderTableSize(4096); 634 assert_eq!(setting_header_table_size.setting_identifier(), 0x01); 635 636 let setting_enable_push = Setting::EnablePush(true); 637 assert_eq!(setting_enable_push.setting_identifier(), 0x02); 638 639 let setting_max_concurrent_streams = Setting::MaxConcurrentStreams(100); 640 assert_eq!(setting_max_concurrent_streams.setting_identifier(), 0x03); 641 642 let setting_initial_window_size = Setting::InitialWindowSize(5000); 643 assert_eq!(setting_initial_window_size.setting_identifier(), 0x04); 644 645 let setting_max_frame_size = Setting::MaxFrameSize(16384); 646 assert_eq!(setting_max_frame_size.setting_identifier(), 0x05); 647 648 let setting_max_header_list_size = Setting::MaxHeaderListSize(8192); 649 assert_eq!(setting_max_header_list_size.setting_identifier(), 0x06); 650 } 651 652 /// UT test cases for `Settings`. 653 /// 654 /// # Brief 655 /// 1. Creates a `Settings` instance with a list of settings. 656 /// 2. Checks if the list of settings in the `Settings` instance is correct. 657 /// 3. Checks if the encoded length of the settings is correct. 658 #[test] ut_settings()659 fn ut_settings() { 660 let settings_list = vec![ 661 Setting::HeaderTableSize(4096), 662 Setting::EnablePush(true), 663 Setting::MaxFrameSize(16384), 664 Setting::MaxHeaderListSize(8192), 665 ]; 666 let settings = Settings::new(settings_list.clone()); 667 assert_eq!(settings.get_settings(), settings_list.as_slice()); 668 669 let encoded_len = settings.encoded_len(); 670 assert_eq!(encoded_len, settings_list.len() * 6); 671 } 672 673 /// UT test cases for `Payload`. 674 /// 675 /// # Brief 676 /// 1. Creates an instance of `Payload` for each possible variant. 677 /// 2. Checks if the `frame_type` of the `Payload` instance is correct. 678 /// 3. Checks if `as_headers` method returns Some or None correctly. 679 #[test] ut_payload()680 fn ut_payload() { 681 let payload_headers = Payload::Headers(Headers::new(Parts::new())); 682 assert_eq!(payload_headers.frame_type(), FrameType::Headers); 683 assert!(payload_headers.as_headers().is_some()); 684 685 let payload_data = Payload::Data(Data::new(b"hh".to_vec())); 686 assert_eq!(payload_data.frame_type(), FrameType::Data); 687 assert!(payload_data.as_headers().is_none()); 688 689 let payload_priority = Payload::Priority(Priority::new(true, 1, 10)); 690 assert_eq!(payload_priority.frame_type(), FrameType::Priority); 691 assert!(payload_priority.as_headers().is_none()); 692 693 let payload_rst_stream = Payload::RstStream(RstStream::new(20)); 694 assert_eq!(payload_rst_stream.frame_type(), FrameType::RstStream); 695 assert!(payload_rst_stream.as_headers().is_none()); 696 697 let payload_ping = Payload::Ping(Ping::new([0; 8])); 698 assert_eq!(payload_ping.frame_type(), FrameType::Ping); 699 assert!(payload_ping.as_headers().is_none()); 700 701 let payload_goaway = Payload::Goaway(Goaway::new(30, 20, vec![0; 0])); 702 assert_eq!(payload_goaway.frame_type(), FrameType::Goaway); 703 assert!(payload_goaway.as_headers().is_none()); 704 705 let payload_window_update = Payload::WindowUpdate(WindowUpdate::new(1024)); 706 assert_eq!(payload_window_update.frame_type(), FrameType::WindowUpdate); 707 assert!(payload_window_update.as_headers().is_none()); 708 709 let payload_push_promise = Payload::PushPromise(PushPromise::new(3, Parts::new())); 710 assert_eq!(payload_push_promise.frame_type(), FrameType::PushPromise); 711 assert!(payload_push_promise.as_headers().is_none()); 712 } 713 } 714