1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //! HTTP [`Status Codes`]. 15 //! 16 //! The status code of a response is a three-digit integer code that describes 17 //! the result of the request and the semantics of the response, including 18 //! whether the request was successful and what content is enclosed (if any). 19 //! All valid status codes are within the range of 100 to 599, inclusive. 20 //! 21 //! [`Status Codes`]: https://httpwg.org/specs/rfc9110.html#status.codes 22 23 use core::convert::TryFrom; 24 use core::fmt::{Display, Formatter}; 25 26 use crate::error::{ErrorKind, HttpError}; 27 28 /// HTTP [`Status Codes`] implementation. 29 /// 30 /// [`Status Codes`]: https://httpwg.org/specs/rfc9110.html#status.codes 31 /// 32 /// # Examples 33 /// 34 /// ``` 35 /// use ylong_http::response::status::StatusCode; 36 /// 37 /// let status = StatusCode::OK; 38 /// ``` 39 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 40 pub struct StatusCode(u16); 41 42 impl StatusCode { 43 /// Converts a `u16` to a `StatusCode`. 44 /// 45 /// # Examples 46 /// ``` 47 /// use ylong_http::response::status::StatusCode; 48 /// 49 /// assert_eq!(StatusCode::from_u16(200), Ok(StatusCode::OK)); 50 /// ``` from_u16(code: u16) -> Result<StatusCode, HttpError>51 pub fn from_u16(code: u16) -> Result<StatusCode, HttpError> { 52 // Only three-digit status codes are valid. 53 if !(100..1000).contains(&code) { 54 return Err(ErrorKind::InvalidInput.into()); 55 } 56 57 Ok(StatusCode(code)) 58 } 59 60 /// Converts a `StatusCode` to a `u16`. 61 /// 62 /// # Examples 63 /// ``` 64 /// use ylong_http::response::status::StatusCode; 65 /// 66 /// assert_eq!(StatusCode::OK.as_u16(), 200u16); 67 /// ``` as_u16(&self) -> u1668 pub fn as_u16(&self) -> u16 { 69 self.0 70 } 71 72 /// Converts a `&[u8]` to a `StatusCode`. 73 /// 74 /// # Example 75 /// ``` 76 /// use ylong_http::response::status::StatusCode; 77 /// 78 /// assert_eq!(StatusCode::from_bytes(b"200"), Ok(StatusCode::OK)); 79 /// assert!(StatusCode::from_bytes(b"0").is_err()); 80 /// ``` from_bytes(bytes: &[u8]) -> Result<Self, HttpError>81 pub fn from_bytes(bytes: &[u8]) -> Result<Self, HttpError> { 82 // Only three-digit status codes are valid. 83 if bytes.len() != 3 { 84 return Err(ErrorKind::InvalidInput.into()); 85 } 86 87 let a = bytes[0].wrapping_sub(b'0') as u16; 88 let b = bytes[1].wrapping_sub(b'0') as u16; 89 let c = bytes[2].wrapping_sub(b'0') as u16; 90 91 if a == 0 || a > 9 || b > 9 || c > 9 { 92 return Err(ErrorKind::InvalidInput.into()); 93 } 94 95 // Valid status code: 1 <= a <= 9 && 0 <= b <= 9 && 0 <= c <= 9 96 Ok(StatusCode((a * 100) + (b * 10) + c)) 97 } 98 99 /// Converts a `StatusCode` to a `[u8; 3]`. 100 /// 101 /// # Example 102 /// ``` 103 /// use ylong_http::response::status::StatusCode; 104 /// 105 /// assert_eq!(StatusCode::OK.as_bytes(), *b"200"); 106 /// ``` as_bytes(&self) -> [u8107 pub fn as_bytes(&self) -> [u8; 3] { 108 [ 109 ((self.0 / 100) as u8) + b'0', 110 (((self.0 % 100) / 10) as u8) + b'0', 111 ((self.0 % 10) as u8) + b'0', 112 ] 113 } 114 115 /// Determines whether the `StatusCode` is [`1xx (Informational)`]. 116 /// 117 /// The 1xx (Informational) class of status code indicates an interim 118 /// response for communicating connection status or request progress prior 119 /// to completing the requested action and sending a final response. 120 /// 121 /// [`1xx (Informational)`]: https://httpwg.org/specs/rfc9110.html#status.1xx 122 /// 123 /// # Examples 124 /// ``` 125 /// use ylong_http::response::status::StatusCode; 126 /// 127 /// assert!(StatusCode::CONTINUE.is_informational()); 128 /// assert!(!StatusCode::OK.is_informational()); 129 /// ``` is_informational(&self) -> bool130 pub fn is_informational(&self) -> bool { 131 self.0 >= 100 && 200 > self.0 132 } 133 134 /// Determines whether the `StatusCode` is [`2xx (Successful)`]. 135 /// 136 /// The 2xx (Successful) class of status code indicates that the client's 137 /// request was successfully received, understood, and accepted. 138 /// 139 /// [`2xx (Successful)`]: https://httpwg.org/specs/rfc9110.html#status.2xx 140 /// 141 /// # Examples 142 /// ``` 143 /// use ylong_http::response::status::StatusCode; 144 /// 145 /// assert!(StatusCode::OK.is_successful()); 146 /// assert!(!StatusCode::CONTINUE.is_successful()); 147 /// ``` is_successful(&self) -> bool148 pub fn is_successful(&self) -> bool { 149 self.0 >= 200 && 300 > self.0 150 } 151 152 /// Determines whether the `StatusCode` is [`3xx (Redirection)`]. 153 /// 154 /// The 3xx (Redirection) class of status code indicates that further action 155 /// needs to be taken by the user agent in order to fulfill the request. 156 /// 157 /// [`3xx (Redirection)`]: https://httpwg.org/specs/rfc9110.html#status.3xx 158 /// 159 /// # Examples 160 /// ``` 161 /// use ylong_http::response::status::StatusCode; 162 /// 163 /// assert!(StatusCode::MULTIPLE_CHOICES.is_redirection()); 164 /// assert!(!StatusCode::OK.is_redirection()); 165 /// ``` is_redirection(&self) -> bool166 pub fn is_redirection(&self) -> bool { 167 self.0 >= 300 && 400 > self.0 168 } 169 170 /// Determines whether the `StatusCode` is [`4xx (Client Error)`]. 171 /// 172 /// The 4xx (Client Error) class of status code indicates that the client 173 /// seems to have erred. 174 /// 175 /// [`4xx (Client Error)`]: https://httpwg.org/specs/rfc9110.html#status.4xx 176 /// 177 /// # Examples 178 /// ``` 179 /// use ylong_http::response::status::StatusCode; 180 /// 181 /// assert!(StatusCode::BAD_REQUEST.is_client_error()); 182 /// assert!(!StatusCode::OK.is_client_error()); 183 /// ``` is_client_error(&self) -> bool184 pub fn is_client_error(&self) -> bool { 185 self.0 >= 400 && 500 > self.0 186 } 187 188 /// Determines whether the `StatusCode` is [`5xx (Server Error)`]. 189 /// 190 /// The 5xx (Server Error) class of status code indicates that the server is 191 /// aware that it has erred or is incapable of performing the requested 192 /// method. 193 /// 194 /// [`5xx (Server Error)`]: https://httpwg.org/specs/rfc9110.html#status.5xx 195 /// 196 /// # Examples 197 /// ``` 198 /// use ylong_http::response::status::StatusCode; 199 /// 200 /// assert!(StatusCode::INTERNAL_SERVER_ERROR.is_server_error()); 201 /// assert!(!StatusCode::OK.is_server_error()); 202 /// ``` is_server_error(&self) -> bool203 pub fn is_server_error(&self) -> bool { 204 self.0 >= 500 && 600 > self.0 205 } 206 } 207 208 impl TryFrom<u16> for StatusCode { 209 type Error = HttpError; 210 try_from(value: u16) -> Result<Self, Self::Error>211 fn try_from(value: u16) -> Result<Self, Self::Error> { 212 Self::from_u16(value) 213 } 214 } 215 216 impl<'a> TryFrom<&'a [u8]> for StatusCode { 217 type Error = HttpError; 218 try_from(value: &'a [u8]) -> Result<Self, Self::Error>219 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> { 220 Self::from_bytes(value) 221 } 222 } 223 224 macro_rules! status_list { 225 ( 226 $( 227 $(#[$docs: meta])* 228 ($num:expr, $name: ident, $phrase: expr), 229 )* 230 ) => { 231 impl StatusCode { 232 $( 233 $(#[$docs])* 234 pub const $name: StatusCode = StatusCode($num as u16); 235 )* 236 237 /// Gets the reason of the `StatusCode`. 238 /// 239 /// # Examples 240 /// 241 /// ``` 242 /// use ylong_http::response::status::StatusCode; 243 /// 244 /// assert_eq!(StatusCode::OK.reason(), Some("OK")); 245 /// ``` 246 pub fn reason(&self) -> Option<&'static str> { 247 match self.0 { 248 $( 249 $num => Some($phrase), 250 )* 251 _ => None, 252 } 253 } 254 } 255 256 /// UT test cases for `StatusCode::reason`. 257 /// 258 /// # Brief 259 /// 1. Creates all the valid `StatusCode`s. 260 /// 2. Calls `StatusCode::reason` on them. 261 /// 3. Checks if the results are correct. 262 #[test] 263 pub fn ut_status_code_reason() { 264 $( 265 assert_eq!(StatusCode::from_u16($num as u16).unwrap().reason(), Some($phrase)); 266 )* 267 assert_eq!(StatusCode::from_u16(999).unwrap().reason(), None); 268 } 269 } 270 } 271 272 // TODO: Adapter, remove this later. 273 impl Display for StatusCode { fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result274 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 275 write!( 276 f, 277 "{} {}", 278 self.as_u16(), 279 self.reason().unwrap_or("Unknown status code") 280 ) 281 } 282 } 283 284 #[rustfmt::skip] 285 status_list!( 286 /// [`100 Continue`]: https://tools.ietf.org/html/rfc7231#section-6.2.1 287 (100, CONTINUE, "Continue"), 288 289 /// [`101 Switching Protocols`]: https://tools.ietf.org/html/rfc7231#section-6.2.2 290 (101, SWITCHING_PROTOCOLS, "Switching Protocols"), 291 292 /// [`102 Processing`]: https://tools.ietf.org/html/rfc2518 293 (102, PROCESSING, "Processing"), 294 295 /// [`200 OK`]: https://tools.ietf.org/html/rfc7231#section-6.3.1 296 (200, OK, "OK"), 297 298 /// [`201 Created`]: https://tools.ietf.org/html/rfc7231#section-6.3.2 299 (201, CREATED, "Created"), 300 301 /// [`202 Accepted`]: https://tools.ietf.org/html/rfc7231#section-6.3.3 302 (202, ACCEPTED, "Accepted"), 303 304 /// [`203 Non-Authoritative Information`]: https://tools.ietf.org/html/rfc7231#section-6.3.4 305 (203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information"), 306 307 /// [`204 No Content`]: https://tools.ietf.org/html/rfc7231#section-6.3.5 308 (204, NO_CONTENT, "No Content"), 309 310 /// [`205 Reset Content`]: https://tools.ietf.org/html/rfc7231#section-6.3.6 311 (205, RESET_CONTENT, "Reset Content"), 312 313 /// [`206 Partial Content`]: https://tools.ietf.org/html/rfc7233#section-4.1 314 (206, PARTIAL_CONTENT, "Partial Content"), 315 316 /// [`207 Multi-Status`]: https://tools.ietf.org/html/rfc4918 317 (207, MULTI_STATUS, "Multi-Status"), 318 319 /// [`208 Already Reported`]: https://tools.ietf.org/html/rfc5842 320 (208, ALREADY_REPORTED, "Already Reported"), 321 322 /// [`226 IM Used`]: https://tools.ietf.org/html/rfc3229 323 (226, IM_USED, "IM Used"), 324 325 /// [`300 Multiple Choices`]: https://tools.ietf.org/html/rfc7231#section-6.4.1 326 (300, MULTIPLE_CHOICES, "Multiple Choices"), 327 328 /// [`301 Moved Permanently`]: https://tools.ietf.org/html/rfc7231#section-6.4.2 329 (301, MOVED_PERMANENTLY, "Moved Permanently"), 330 331 /// [`302 Found`]: https://tools.ietf.org/html/rfc7231#section-6.4.3 332 (302, FOUND, "Found"), 333 334 /// [`303 See Other`]: https://tools.ietf.org/html/rfc7231#section-6.4.4 335 (303, SEE_OTHER, "See Other"), 336 337 /// [`304 Not Modified`]: https://tools.ietf.org/html/rfc7232#section-4.1 338 (304, NOT_MODIFIED, "Not Modified"), 339 340 /// [`305 Use Proxy`]: https://tools.ietf.org/html/rfc7231#section-6.4.5 341 (305, USE_PROXY, "Use Proxy"), 342 343 /// [`307 Temporary Redirect`]: https://tools.ietf.org/html/rfc7231#section-6.4.7 344 (307, TEMPORARY_REDIRECT, "Temporary Redirect"), 345 346 /// [`308 Permanent Redirect`]: https://tools.ietf.org/html/rfc7238 347 (308, PERMANENT_REDIRECT, "Permanent Redirect"), 348 349 /// [`400 Bad Request`]: https://tools.ietf.org/html/rfc7231#section-6.5.1 350 (400, BAD_REQUEST, "Bad Request"), 351 352 /// [`401 Unauthorized`]: https://tools.ietf.org/html/rfc7235#section-3.1 353 (401, UNAUTHORIZED, "Unauthorized"), 354 355 /// [`402 Payment Required`]: https://tools.ietf.org/html/rfc7231#section-6.5.2 356 (402, PAYMENT_REQUIRED, "Payment Required"), 357 358 /// [`403 Forbidden`]: https://tools.ietf.org/html/rfc7231#section-6.5.3 359 (403, FORBIDDEN, "Forbidden"), 360 361 /// [`404 Not Found`]: https://tools.ietf.org/html/rfc7231#section-6.5.4 362 (404, NOT_FOUND, "Not Found"), 363 364 /// [`405 Method Not Allowed`]: https://tools.ietf.org/html/rfc7231#section-6.5.5 365 (405, METHOD_NOT_ALLOWED, "Method Not Allowed"), 366 367 /// [`406 Not Acceptable`]: https://tools.ietf.org/html/rfc7231#section-6.5.6 368 (406, NOT_ACCEPTABLE, "Not Acceptable"), 369 370 /// [`407 Proxy Authentication Required`]: https://tools.ietf.org/html/rfc7235#section-3.2 371 (407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required"), 372 373 /// [`408 Request Timeout`]: https://tools.ietf.org/html/rfc7231#section-6.5.7 374 (408, REQUEST_TIMEOUT, "Request Timeout"), 375 376 /// [`409 Conflict`]: https://tools.ietf.org/html/rfc7231#section-6.5.8 377 (409, CONFLICT, "Conflict"), 378 379 /// [`410 Gone`]: https://tools.ietf.org/html/rfc7231#section-6.5.9 380 (410, GONE, "Gone"), 381 382 /// [`411 Length Required`]: https://tools.ietf.org/html/rfc7231#section-6.5.10 383 (411, LENGTH_REQUIRED, "Length Required"), 384 385 /// [`412 Precondition Failed`]: https://tools.ietf.org/html/rfc7232#section-4.2 386 (412, PRECONDITION_FAILED, "Precondition Failed"), 387 388 /// [`413 Payload Too Large`]: https://tools.ietf.org/html/rfc7231#section-6.5.11 389 (413, PAYLOAD_TOO_LARGE, "Payload Too Large"), 390 391 /// [`414 URI Too Long`]: https://tools.ietf.org/html/rfc7231#section-6.5.12 392 (414, URI_TOO_LONG, "URI Too Long"), 393 394 /// [`415 Unsupported Media Type`]: https://tools.ietf.org/html/rfc7231#section-6.5.13 395 (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type"), 396 397 /// [`416 Range Not Satisfiable`]: https://tools.ietf.org/html/rfc7233#section-4.4 398 (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable"), 399 400 /// [`417 Expectation Failed`]: https://tools.ietf.org/html/rfc7231#section-6.5.14 401 (417, EXPECTATION_FAILED, "Expectation Failed"), 402 403 /// [`418 I'm a teapot`]: https://tools.ietf.org/html/rfc2324 404 (418, IM_A_TEAPOT, "I'm a teapot"), 405 406 /// [`421 Misdirected Request`]: http://tools.ietf.org/html/rfc7540#section-9.1.2 407 (421, MISDIRECTED_REQUEST, "Misdirected Request"), 408 409 /// [`422 Unprocessable Entity`]: https://tools.ietf.org/html/rfc4918 410 (422, UNPROCESSABLE_ENTITY, "Unprocessable Entity"), 411 412 /// [`423 Locked`]: https://tools.ietf.org/html/rfc4918 413 (423, LOCKED, "Locked"), 414 415 /// [`424 Failed Dependency`]: https://tools.ietf.org/html/rfc4918 416 (424, FAILED_DEPENDENCY, "Failed Dependency"), 417 418 /// [`426 Upgrade Required`]: https://tools.ietf.org/html/rfc7231#section-6.5.15 419 (426, UPGRADE_REQUIRED, "Upgrade Required"), 420 421 /// [`428 Precondition Required`]: https://tools.ietf.org/html/rfc6585 422 (428, PRECONDITION_REQUIRED, "Precondition Required"), 423 424 /// [`429 Too Many Requests`]: https://tools.ietf.org/html/rfc6585 425 (429, TOO_MANY_REQUESTS, "Too Many Requests"), 426 427 /// [`431 Request Header Fields Too Large`]: https://tools.ietf.org/html/rfc6585 428 (431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large"), 429 430 /// [`451 Unavailable For Legal Reasons`]: http://tools.ietf.org/html/rfc7725 431 (451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons"), 432 433 /// [`500 Internal Server Error`]: https://tools.ietf.org/html/rfc7231#section-6.6.1 434 (500, INTERNAL_SERVER_ERROR, "Internal Server Error"), 435 436 /// [`501 Not Implemented`]: https://tools.ietf.org/html/rfc7231#section-6.6.2 437 (501, NOT_IMPLEMENTED, "Not Implemented"), 438 439 /// [`502 Bad Gateway`]: https://tools.ietf.org/html/rfc7231#section-6.6.3 440 (502, BAD_GATEWAY, "Bad Gateway"), 441 442 /// [`503 Service Unavailable`]: https://tools.ietf.org/html/rfc7231#section-6.6.4 443 (503, SERVICE_UNAVAILABLE, "Service Unavailable"), 444 445 /// [`504 Gateway Timeout`]: https://tools.ietf.org/html/rfc7231#section-6.6.5 446 (504, GATEWAY_TIMEOUT, "Gateway Timeout"), 447 448 /// [`505 HTTP Version Not Supported`]: https://tools.ietf.org/html/rfc7231#section-6.6.6 449 (505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported"), 450 451 /// [`506 Variant Also Negotiates`]: https://tools.ietf.org/html/rfc2295 452 (506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates"), 453 454 /// [`507 Insufficient Storage`]: https://tools.ietf.org/html/rfc4918 455 (507, INSUFFICIENT_STORAGE, "Insufficient Storage"), 456 457 /// [`508 Loop Detected`]: https://tools.ietf.org/html/rfc5842 458 (508, LOOP_DETECTED, "Loop Detected"), 459 460 /// [`510 Not Extended`]: https://tools.ietf.org/html/rfc2774 461 (510, NOT_EXTENDED, "Not Extended"), 462 463 /// [`511 Network Authentication Required`]: https://tools.ietf.org/html/rfc6585 464 (511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required"), 465 ); 466 467 #[cfg(test)] 468 mod ut_status_code { 469 use super::StatusCode; 470 use crate::error::{ErrorKind, HttpError}; 471 472 /// UT test cases for `StatusCode::from_bytes`. 473 /// 474 /// # Brief 475 /// 1. Calls `StatusCode::from_bytes` with various inputs. 476 /// 2. Checks if the results are correct. 477 #[test] ut_status_code_from_u16()478 fn ut_status_code_from_u16() { 479 // Normal Test Cases: 480 assert_eq!(StatusCode::from_u16(100), Ok(StatusCode::CONTINUE)); 481 assert!(StatusCode::from_u16(999).is_ok()); 482 483 // Exception Test Cases: 484 // 1. The given number is not in the range of 100 to 1000. 485 assert_eq!( 486 StatusCode::from_u16(0), 487 Err(HttpError::from(ErrorKind::InvalidInput)) 488 ); 489 assert_eq!( 490 StatusCode::from_u16(u16::MAX), 491 Err(HttpError::from(ErrorKind::InvalidInput)) 492 ); 493 } 494 495 /// UT test cases for `StatusCode::as_u16`. 496 /// 497 /// # Brief 498 /// 1. Creates a `StatusCode`. 499 /// 2. Calls `StatusCode::as_u16` on it. 500 /// 3. Checks if the result is correct. 501 #[test] ut_status_code_as_u16()502 fn ut_status_code_as_u16() { 503 assert_eq!(StatusCode::OK.as_u16(), 200); 504 } 505 506 /// UT test cases for `StatusCode::from_bytes`. 507 /// 508 /// # Brief 509 /// 1. Calls `StatusCode::from_bytes` with various inputs. 510 /// 2. Checks if the results are correct. 511 #[test] ut_status_code_from_bytes()512 fn ut_status_code_from_bytes() { 513 // Normal Test Cases: 514 assert_eq!(StatusCode::from_bytes(b"100"), Ok(StatusCode::CONTINUE)); 515 assert_eq!( 516 StatusCode::from_bytes(b"500"), 517 Ok(StatusCode::INTERNAL_SERVER_ERROR) 518 ); 519 assert!(StatusCode::from_bytes(b"999").is_ok()); 520 521 // Exception Test Cases: 522 // 1. Empty bytes slice. 523 assert_eq!( 524 StatusCode::from_bytes(b""), 525 Err(HttpError::from(ErrorKind::InvalidInput)) 526 ); 527 528 // 2. The length of the bytes slice is not 3. 529 assert_eq!( 530 StatusCode::from_bytes(b"1"), 531 Err(HttpError::from(ErrorKind::InvalidInput)) 532 ); 533 assert_eq!( 534 StatusCode::from_bytes(b"1000"), 535 Err(HttpError::from(ErrorKind::InvalidInput)) 536 ); 537 538 // 3. Other error branch coverage test cases. 539 assert_eq!( 540 StatusCode::from_bytes(b"099"), 541 Err(HttpError::from(ErrorKind::InvalidInput)) 542 ); 543 assert_eq!( 544 StatusCode::from_bytes(b"a99"), 545 Err(HttpError::from(ErrorKind::InvalidInput)) 546 ); 547 assert_eq!( 548 StatusCode::from_bytes(b"1a9"), 549 Err(HttpError::from(ErrorKind::InvalidInput)) 550 ); 551 assert_eq!( 552 StatusCode::from_bytes(b"19a"), 553 Err(HttpError::from(ErrorKind::InvalidInput)) 554 ); 555 assert_eq!( 556 StatusCode::from_bytes(b"\n\n\n"), 557 Err(HttpError::from(ErrorKind::InvalidInput)) 558 ); 559 } 560 561 /// UT test cases for `StatusCode::is_informational`. 562 /// 563 /// # Brief 564 /// 1. Creates some `StatusCode`s that have different type with each other. 565 /// 2. Calls `StatusCode::is_informational` on them. 566 /// 3. Checks if the results are correct. 567 #[test] ut_status_code_is_informational()568 fn ut_status_code_is_informational() { 569 assert!(StatusCode::CONTINUE.is_informational()); 570 assert!(!StatusCode::OK.is_informational()); 571 assert!(!StatusCode::MULTIPLE_CHOICES.is_informational()); 572 assert!(!StatusCode::BAD_REQUEST.is_informational()); 573 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_informational()); 574 assert!(!StatusCode::from_u16(999).unwrap().is_informational()); 575 } 576 577 /// UT test cases for `StatusCode::is_successful`. 578 /// 579 /// # Brief 580 /// 1. Creates some `StatusCode`s that have different type with each other. 581 /// 2. Calls `StatusCode::is_successful` on them. 582 /// 3. Checks if the results are correct. 583 #[test] ut_status_code_is_successful()584 fn ut_status_code_is_successful() { 585 assert!(!StatusCode::CONTINUE.is_successful()); 586 assert!(StatusCode::OK.is_successful()); 587 assert!(!StatusCode::MULTIPLE_CHOICES.is_successful()); 588 assert!(!StatusCode::BAD_REQUEST.is_successful()); 589 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_successful()); 590 assert!(!StatusCode::from_u16(999).unwrap().is_successful()); 591 } 592 593 /// UT test cases for `StatusCode::is_redirection`. 594 /// 595 /// # Brief 596 /// 1. Creates some `StatusCode`s that have different type with each other. 597 /// 2. Calls `StatusCode::is_redirection` on them. 598 /// 3. Checks if the results are correct. 599 #[test] ut_status_code_is_redirection()600 fn ut_status_code_is_redirection() { 601 assert!(!StatusCode::CONTINUE.is_redirection()); 602 assert!(!StatusCode::OK.is_redirection()); 603 assert!(StatusCode::MULTIPLE_CHOICES.is_redirection()); 604 assert!(!StatusCode::BAD_REQUEST.is_redirection()); 605 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_redirection()); 606 assert!(!StatusCode::from_u16(999).unwrap().is_redirection()); 607 } 608 609 /// UT test cases for `StatusCode::is_client_error`. 610 /// 611 /// # Brief 612 /// 1. Creates some `StatusCode`s that have different type with each other. 613 /// 2. Calls `StatusCode::is_client_error` on them. 614 /// 3. Checks if the results are correct. 615 #[test] ut_status_code_is_client_error()616 fn ut_status_code_is_client_error() { 617 assert!(!StatusCode::CONTINUE.is_client_error()); 618 assert!(!StatusCode::OK.is_client_error()); 619 assert!(!StatusCode::MULTIPLE_CHOICES.is_client_error()); 620 assert!(StatusCode::BAD_REQUEST.is_client_error()); 621 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_client_error()); 622 assert!(!StatusCode::from_u16(999).unwrap().is_client_error()); 623 } 624 625 /// UT test cases for `StatusCode::is_server_error`. 626 /// 627 /// # Brief 628 /// 1. Creates some `StatusCode`s that have different type with each other. 629 /// 2. Calls `StatusCode::is_server_error` on them. 630 /// 3. Checks if the results are correct. 631 #[test] ut_status_code_is_server_error()632 fn ut_status_code_is_server_error() { 633 assert!(!StatusCode::CONTINUE.is_server_error()); 634 assert!(!StatusCode::OK.is_server_error()); 635 assert!(!StatusCode::MULTIPLE_CHOICES.is_server_error()); 636 assert!(!StatusCode::BAD_REQUEST.is_server_error()); 637 assert!(StatusCode::INTERNAL_SERVER_ERROR.is_server_error()); 638 assert!(!StatusCode::from_u16(999).unwrap().is_server_error()); 639 } 640 641 /// UT test cases for `StatusCode::as_bytes`. 642 /// 643 /// # Brief 644 /// 1. Creates some `StatusCode`s that have different type with each other. 645 /// 2. Calls `StatusCode::as_bytes` on them. 646 /// 3. Checks if the results are correct. 647 #[test] ut_status_code_as_bytes()648 fn ut_status_code_as_bytes() { 649 assert_eq!(StatusCode::OK.as_bytes(), *b"200"); 650 assert_eq!(StatusCode::FOUND.as_bytes(), *b"302"); 651 assert_eq!(StatusCode::NOT_FOUND.as_bytes(), *b"404"); 652 assert_eq!(StatusCode::GATEWAY_TIMEOUT.as_bytes(), *b"504"); 653 } 654 } 655