1515//! ```
1616
1717use std:: convert:: TryFrom ;
18+ use std:: num:: NonZeroU16 ;
1819use std:: error:: Error ;
1920use std:: fmt;
2021use std:: str:: FromStr ;
2122
2223/// An HTTP status code (`status-code` in RFC 7230 et al.).
2324///
24- /// This type contains constants for all common status codes.
25- /// It allows status codes in the range [100, 599].
25+ /// Constants are provided for known status codes, including those in the IANA
26+ /// [HTTP Status Code Registry](
27+ /// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml).
2628///
27- /// IANA maintain the [Hypertext Transfer Protocol (HTTP) Status Code
28- /// Registry](http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) which is
29- /// the source for this enum (with one exception, 418 I'm a teapot, which is
30- /// inexplicably not in the register).
29+ /// Status code values in the range 100-999 (inclusive) are supported by this
30+ /// type. Values in the range 100-599 are semantically classified by the most
31+ /// significant digit. See [`StatusCode::is_success`], etc. Values above 599
32+ /// are unclassified but allowed for legacy compatibility, though their use is
33+ /// discouraged. Applications may interpret such values as protocol errors.
3134///
3235/// # Examples
3336///
@@ -39,12 +42,12 @@ use std::str::FromStr;
3942/// assert!(StatusCode::OK.is_success());
4043/// ```
4144#[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
42- pub struct StatusCode ( u16 ) ;
45+ pub struct StatusCode ( NonZeroU16 ) ;
4346
4447/// A possible error value when converting a `StatusCode` from a `u16` or `&str`
4548///
4649/// This error indicates that the supplied input was not a valid number, was less
47- /// than 100, or was greater than 599 .
50+ /// than 100, or was greater than 999 .
4851pub struct InvalidStatusCode {
4952 _priv : ( ) ,
5053}
@@ -53,7 +56,7 @@ impl StatusCode {
5356 /// Converts a u16 to a status code.
5457 ///
5558 /// The function validates the correctness of the supplied u16. It must be
56- /// greater or equal to 100 but less than 600 .
59+ /// greater or equal to 100 and less than 1000 .
5760 ///
5861 /// # Example
5962 ///
@@ -68,11 +71,13 @@ impl StatusCode {
6871 /// ```
6972 #[ inline]
7073 pub fn from_u16 ( src : u16 ) -> Result < StatusCode , InvalidStatusCode > {
71- if src < 100 || src >= 600 {
74+ if src < 100 || src >= 1000 {
7275 return Err ( InvalidStatusCode :: new ( ) ) ;
7376 }
7477
75- Ok ( StatusCode ( src) )
78+ NonZeroU16 :: new ( src)
79+ . map ( StatusCode )
80+ . ok_or_else ( InvalidStatusCode :: new)
7681 }
7782
7883 /// Converts a &[u8] to a status code
@@ -85,12 +90,14 @@ impl StatusCode {
8590 let b = src[ 1 ] . wrapping_sub ( b'0' ) as u16 ;
8691 let c = src[ 2 ] . wrapping_sub ( b'0' ) as u16 ;
8792
88- if a == 0 || a > 5 || b > 9 || c > 9 {
93+ if a == 0 || a > 9 || b > 9 || c > 9 {
8994 return Err ( InvalidStatusCode :: new ( ) ) ;
9095 }
9196
9297 let status = ( a * 100 ) + ( b * 10 ) + c;
93- Ok ( StatusCode ( status) )
98+ NonZeroU16 :: new ( status)
99+ . map ( StatusCode )
100+ . ok_or_else ( InvalidStatusCode :: new)
94101 }
95102
96103 /// Returns the `u16` corresponding to this `StatusCode`.
@@ -126,7 +133,17 @@ impl StatusCode {
126133 /// ```
127134 #[ inline]
128135 pub fn as_str ( & self ) -> & str {
129- CODES_AS_STR [ ( self . 0 - 100 ) as usize ]
136+ let offset = ( self . 0 . get ( ) - 100 ) as usize ;
137+ let offset = offset * 3 ;
138+
139+ // Invariant: self has checked range [100, 999] and CODE_DIGITS is
140+ // ASCII-only, of length 900 * 3 = 2700 bytes
141+
142+ #[ cfg( debug_assertions) ]
143+ { & CODE_DIGITS [ offset..offset+3 ] }
144+
145+ #[ cfg( not( debug_assertions) ) ]
146+ unsafe { CODE_DIGITS . get_unchecked ( offset..offset+3 ) }
130147 }
131148
132149 /// Get the standardised `reason-phrase` for this status code.
@@ -148,37 +165,37 @@ impl StatusCode {
148165 /// assert_eq!(status.canonical_reason(), Some("OK"));
149166 /// ```
150167 pub fn canonical_reason ( & self ) -> Option < & ' static str > {
151- canonical_reason ( self . 0 )
168+ canonical_reason ( self . 0 . get ( ) )
152169 }
153170
154171 /// Check if status is within 100-199.
155172 #[ inline]
156173 pub fn is_informational ( & self ) -> bool {
157- 200 > self . 0 && self . 0 >= 100
174+ 200 > self . 0 . get ( ) && self . 0 . get ( ) >= 100
158175 }
159176
160177 /// Check if status is within 200-299.
161178 #[ inline]
162179 pub fn is_success ( & self ) -> bool {
163- 300 > self . 0 && self . 0 >= 200
180+ 300 > self . 0 . get ( ) && self . 0 . get ( ) >= 200
164181 }
165182
166183 /// Check if status is within 300-399.
167184 #[ inline]
168185 pub fn is_redirection ( & self ) -> bool {
169- 400 > self . 0 && self . 0 >= 300
186+ 400 > self . 0 . get ( ) && self . 0 . get ( ) >= 300
170187 }
171188
172189 /// Check if status is within 400-499.
173190 #[ inline]
174191 pub fn is_client_error ( & self ) -> bool {
175- 500 > self . 0 && self . 0 >= 400
192+ 500 > self . 0 . get ( ) && self . 0 . get ( ) >= 400
176193 }
177194
178195 /// Check if status is within 500-599.
179196 #[ inline]
180197 pub fn is_server_error ( & self ) -> bool {
181- 600 > self . 0 && self . 0 >= 500
198+ 600 > self . 0 . get ( ) && self . 0 . get ( ) >= 500
182199 }
183200}
184201
@@ -231,7 +248,7 @@ impl PartialEq<StatusCode> for u16 {
231248impl From < StatusCode > for u16 {
232249 #[ inline]
233250 fn from ( status : StatusCode ) -> u16 {
234- status. 0
251+ status. 0 . get ( )
235252 }
236253}
237254
@@ -287,7 +304,7 @@ macro_rules! status_codes {
287304 impl StatusCode {
288305 $(
289306 $( #[ $docs] ) *
290- pub const $konst: StatusCode = StatusCode ( $num) ;
307+ pub const $konst: StatusCode = StatusCode ( unsafe { NonZeroU16 :: new_unchecked ( $num) } ) ;
291308 ) +
292309
293310 }
@@ -521,40 +538,51 @@ impl fmt::Display for InvalidStatusCode {
521538
522539impl Error for InvalidStatusCode { }
523540
524- macro_rules! status_code_strs {
525- ( $( $num: expr, ) +) => {
526- const CODES_AS_STR : [ & ' static str ; 500 ] = [ $( stringify!( $num) , ) + ] ;
527- }
528- }
529-
530- status_code_strs ! (
531- 100 , 101 , 102 , 103 , 104 , 105 , 106 , 107 , 108 , 109 , 110 , 111 , 112 , 113 , 114 , 115 , 116 , 117 , 118 , 119 ,
532- 120 , 121 , 122 , 123 , 124 , 125 , 126 , 127 , 128 , 129 , 130 , 131 , 132 , 133 , 134 , 135 , 136 , 137 , 138 , 139 ,
533- 140 , 141 , 142 , 143 , 144 , 145 , 146 , 147 , 148 , 149 , 150 , 151 , 152 , 153 , 154 , 155 , 156 , 157 , 158 , 159 ,
534- 160 , 161 , 162 , 163 , 164 , 165 , 166 , 167 , 168 , 169 , 170 , 171 , 172 , 173 , 174 , 175 , 176 , 177 , 178 , 179 ,
535- 180 , 181 , 182 , 183 , 184 , 185 , 186 , 187 , 188 , 189 , 190 , 191 , 192 , 193 , 194 , 195 , 196 , 197 , 198 , 199 ,
536-
537- 200 , 201 , 202 , 203 , 204 , 205 , 206 , 207 , 208 , 209 , 210 , 211 , 212 , 213 , 214 , 215 , 216 , 217 , 218 , 219 ,
538- 220 , 221 , 222 , 223 , 224 , 225 , 226 , 227 , 228 , 229 , 230 , 231 , 232 , 233 , 234 , 235 , 236 , 237 , 238 , 239 ,
539- 240 , 241 , 242 , 243 , 244 , 245 , 246 , 247 , 248 , 249 , 250 , 251 , 252 , 253 , 254 , 255 , 256 , 257 , 258 , 259 ,
540- 260 , 261 , 262 , 263 , 264 , 265 , 266 , 267 , 268 , 269 , 270 , 271 , 272 , 273 , 274 , 275 , 276 , 277 , 278 , 279 ,
541- 280 , 281 , 282 , 283 , 284 , 285 , 286 , 287 , 288 , 289 , 290 , 291 , 292 , 293 , 294 , 295 , 296 , 297 , 298 , 299 ,
542-
543- 300 , 301 , 302 , 303 , 304 , 305 , 306 , 307 , 308 , 309 , 310 , 311 , 312 , 313 , 314 , 315 , 316 , 317 , 318 , 319 ,
544- 320 , 321 , 322 , 323 , 324 , 325 , 326 , 327 , 328 , 329 , 330 , 331 , 332 , 333 , 334 , 335 , 336 , 337 , 338 , 339 ,
545- 340 , 341 , 342 , 343 , 344 , 345 , 346 , 347 , 348 , 349 , 350 , 351 , 352 , 353 , 354 , 355 , 356 , 357 , 358 , 359 ,
546- 360 , 361 , 362 , 363 , 364 , 365 , 366 , 367 , 368 , 369 , 370 , 371 , 372 , 373 , 374 , 375 , 376 , 377 , 378 , 379 ,
547- 380 , 381 , 382 , 383 , 384 , 385 , 386 , 387 , 388 , 389 , 390 , 391 , 392 , 393 , 394 , 395 , 396 , 397 , 398 , 399 ,
548-
549- 400 , 401 , 402 , 403 , 404 , 405 , 406 , 407 , 408 , 409 , 410 , 411 , 412 , 413 , 414 , 415 , 416 , 417 , 418 , 419 ,
550- 420 , 421 , 422 , 423 , 424 , 425 , 426 , 427 , 428 , 429 , 430 , 431 , 432 , 433 , 434 , 435 , 436 , 437 , 438 , 439 ,
551- 440 , 441 , 442 , 443 , 444 , 445 , 446 , 447 , 448 , 449 , 450 , 451 , 452 , 453 , 454 , 455 , 456 , 457 , 458 , 459 ,
552- 460 , 461 , 462 , 463 , 464 , 465 , 466 , 467 , 468 , 469 , 470 , 471 , 472 , 473 , 474 , 475 , 476 , 477 , 478 , 479 ,
553- 480 , 481 , 482 , 483 , 484 , 485 , 486 , 487 , 488 , 489 , 490 , 491 , 492 , 493 , 494 , 495 , 496 , 497 , 498 , 499 ,
554-
555- 500 , 501 , 502 , 503 , 504 , 505 , 506 , 507 , 508 , 509 , 510 , 511 , 512 , 513 , 514 , 515 , 516 , 517 , 518 , 519 ,
556- 520 , 521 , 522 , 523 , 524 , 525 , 526 , 527 , 528 , 529 , 530 , 531 , 532 , 533 , 534 , 535 , 536 , 537 , 538 , 539 ,
557- 540 , 541 , 542 , 543 , 544 , 545 , 546 , 547 , 548 , 549 , 550 , 551 , 552 , 553 , 554 , 555 , 556 , 557 , 558 , 559 ,
558- 560 , 561 , 562 , 563 , 564 , 565 , 566 , 567 , 568 , 569 , 570 , 571 , 572 , 573 , 574 , 575 , 576 , 577 , 578 , 579 ,
559- 580 , 581 , 582 , 583 , 584 , 585 , 586 , 587 , 588 , 589 , 590 , 591 , 592 , 593 , 594 , 595 , 596 , 597 , 598 , 599 ,
560- ) ;
541+ // A string of packed 3-ASCII-digit status code values for the supported range
542+ // of [100, 999] (900 codes, 2700 bytes).
543+ const CODE_DIGITS : & ' static str = "\
544+ 100101102103104105106107108109110111112113114115116117118119\
545+ 120121122123124125126127128129130131132133134135136137138139\
546+ 140141142143144145146147148149150151152153154155156157158159\
547+ 160161162163164165166167168169170171172173174175176177178179\
548+ 180181182183184185186187188189190191192193194195196197198199\
549+ 200201202203204205206207208209210211212213214215216217218219\
550+ 220221222223224225226227228229230231232233234235236237238239\
551+ 240241242243244245246247248249250251252253254255256257258259\
552+ 260261262263264265266267268269270271272273274275276277278279\
553+ 280281282283284285286287288289290291292293294295296297298299\
554+ 300301302303304305306307308309310311312313314315316317318319\
555+ 320321322323324325326327328329330331332333334335336337338339\
556+ 340341342343344345346347348349350351352353354355356357358359\
557+ 360361362363364365366367368369370371372373374375376377378379\
558+ 380381382383384385386387388389390391392393394395396397398399\
559+ 400401402403404405406407408409410411412413414415416417418419\
560+ 420421422423424425426427428429430431432433434435436437438439\
561+ 440441442443444445446447448449450451452453454455456457458459\
562+ 460461462463464465466467468469470471472473474475476477478479\
563+ 480481482483484485486487488489490491492493494495496497498499\
564+ 500501502503504505506507508509510511512513514515516517518519\
565+ 520521522523524525526527528529530531532533534535536537538539\
566+ 540541542543544545546547548549550551552553554555556557558559\
567+ 560561562563564565566567568569570571572573574575576577578579\
568+ 580581582583584585586587588589590591592593594595596597598599\
569+ 600601602603604605606607608609610611612613614615616617618619\
570+ 620621622623624625626627628629630631632633634635636637638639\
571+ 640641642643644645646647648649650651652653654655656657658659\
572+ 660661662663664665666667668669670671672673674675676677678679\
573+ 680681682683684685686687688689690691692693694695696697698699\
574+ 700701702703704705706707708709710711712713714715716717718719\
575+ 720721722723724725726727728729730731732733734735736737738739\
576+ 740741742743744745746747748749750751752753754755756757758759\
577+ 760761762763764765766767768769770771772773774775776777778779\
578+ 780781782783784785786787788789790791792793794795796797798799\
579+ 800801802803804805806807808809810811812813814815816817818819\
580+ 820821822823824825826827828829830831832833834835836837838839\
581+ 840841842843844845846847848849850851852853854855856857858859\
582+ 860861862863864865866867868869870871872873874875876877878879\
583+ 880881882883884885886887888889890891892893894895896897898899\
584+ 900901902903904905906907908909910911912913914915916917918919\
585+ 920921922923924925926927928929930931932933934935936937938939\
586+ 940941942943944945946947948949950951952953954955956957958959\
587+ 960961962963964965966967968969970971972973974975976977978979\
588+ 980981982983984985986987988989990991992993994995996997998999";
0 commit comments