Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make StatusCode allow 600-999 #438

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 58 additions & 18 deletions src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
//! ```

use std::convert::TryFrom;
use std::num::NonZeroU16;
use std::error::Error;
use std::fmt;
use std::str::FromStr;

/// An HTTP status code (`status-code` in RFC 7230 et al.).
///
/// This type contains constants for all common status codes.
/// It allows status codes in the range [100, 599].
/// It allows status codes in the range [100, 999].
///
/// IANA maintain the [Hypertext Transfer Protocol (HTTP) Status Code
/// Registry](http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) which is
Expand All @@ -39,12 +40,12 @@ use std::str::FromStr;
/// assert!(StatusCode::OK.is_success());
/// ```
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StatusCode(u16);
pub struct StatusCode(NonZeroU16);

/// A possible error value when converting a `StatusCode` from a `u16` or `&str`
///
/// This error indicates that the supplied input was not a valid number, was less
/// than 100, or was greater than 599.
/// than 100, or was greater than 999.
pub struct InvalidStatusCode {
_priv: (),
}
Expand All @@ -53,7 +54,7 @@ impl StatusCode {
/// Converts a u16 to a status code.
///
/// The function validates the correctness of the supplied u16. It must be
/// greater or equal to 100 but less than 600.
/// greater or equal to 100 but less than 1000.
///
/// # Example
///
Expand All @@ -68,11 +69,13 @@ impl StatusCode {
/// ```
#[inline]
pub fn from_u16(src: u16) -> Result<StatusCode, InvalidStatusCode> {
if src < 100 || src >= 600 {
if src < 100 || src >= 1000 {
return Err(InvalidStatusCode::new());
}

Ok(StatusCode(src))
NonZeroU16::new(src)
.map(StatusCode)
.ok_or_else(InvalidStatusCode::new)
}

/// Converts a &[u8] to a status code
Expand All @@ -85,12 +88,14 @@ impl StatusCode {
let b = src[1].wrapping_sub(b'0') as u16;
let c = src[2].wrapping_sub(b'0') as u16;

if a == 0 || a > 5 || b > 9 || c > 9 {
if a == 0 || a > 9 || b > 9 || c > 9 {
return Err(InvalidStatusCode::new());
}

let status = (a * 100) + (b * 10) + c;
Ok(StatusCode(status))
NonZeroU16::new(status)
.map(StatusCode)
.ok_or_else(InvalidStatusCode::new)
quininer marked this conversation as resolved.
Show resolved Hide resolved
}

/// Returns the `u16` corresponding to this `StatusCode`.
Expand Down Expand Up @@ -126,7 +131,14 @@ impl StatusCode {
/// ```
#[inline]
pub fn as_str(&self) -> &str {
CODES_AS_STR[(self.0 - 100) as usize]
let offset = (self.0.get() - 100) as usize;
quininer marked this conversation as resolved.
Show resolved Hide resolved
let offset = offset * 3;

unsafe {
CODES_AS_STR
.get_unchecked(offset..)
.get_unchecked(..3)
}
}

/// Get the standardised `reason-phrase` for this status code.
Expand All @@ -148,37 +160,37 @@ impl StatusCode {
/// assert_eq!(status.canonical_reason(), Some("OK"));
/// ```
pub fn canonical_reason(&self) -> Option<&'static str> {
canonical_reason(self.0)
canonical_reason(self.0.get())
}

/// Check if status is within 100-199.
#[inline]
pub fn is_informational(&self) -> bool {
200 > self.0 && self.0 >= 100
200 > self.0.get() && self.0.get() >= 100
}

/// Check if status is within 200-299.
#[inline]
pub fn is_success(&self) -> bool {
300 > self.0 && self.0 >= 200
300 > self.0.get() && self.0.get() >= 200
}

/// Check if status is within 300-399.
#[inline]
pub fn is_redirection(&self) -> bool {
400 > self.0 && self.0 >= 300
400 > self.0.get() && self.0.get() >= 300
}

/// Check if status is within 400-499.
#[inline]
pub fn is_client_error(&self) -> bool {
500 > self.0 && self.0 >= 400
500 > self.0.get() && self.0.get() >= 400
}

/// Check if status is within 500-599.
#[inline]
pub fn is_server_error(&self) -> bool {
600 > self.0 && self.0 >= 500
600 > self.0.get() && self.0.get() >= 500
}
}

Expand Down Expand Up @@ -231,7 +243,7 @@ impl PartialEq<StatusCode> for u16 {
impl From<StatusCode> for u16 {
#[inline]
fn from(status: StatusCode) -> u16 {
status.0
status.0.get()
}
}

Expand Down Expand Up @@ -287,7 +299,7 @@ macro_rules! status_codes {
impl StatusCode {
$(
$(#[$docs])*
pub const $konst: StatusCode = StatusCode($num);
pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) });
)+

}
Expand Down Expand Up @@ -523,7 +535,11 @@ impl Error for InvalidStatusCode {}

macro_rules! status_code_strs {
($($num:expr,)+) => {
const CODES_AS_STR: [&'static str; 500] = [ $( stringify!($num), )+ ];
const CODES_AS_STR: &'static str = concat!(
$(
stringify!($num) ,
)+
);
}
}

Expand Down Expand Up @@ -557,4 +573,28 @@ status_code_strs!(
540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559,
560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599,

600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619,
620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639,
640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659,
660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679,
680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699,

700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719,
720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739,
740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759,
760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779,
780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799,

800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819,
820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839,
840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859,
860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879,
880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899,

900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919,
920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939,
940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959,
960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979,
980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999,
);
28 changes: 26 additions & 2 deletions tests/status_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use http::*;
#[test]
fn from_bytes() {
for ok in &[
"100", "101", "199", "200", "250", "299", "321", "399", "499", "599",
"100", "101", "199", "200", "250", "299", "321", "399", "499", "599", "600", "999"
] {
assert!(StatusCode::from_bytes(ok.as_bytes()).is_ok());
}

for not_ok in &[
"0", "00", "10", "40", "99", "000", "010", "099", "600", "610", "999",
"0", "00", "10", "40", "99", "000", "010", "099", "1000", "1999",
] {
assert!(StatusCode::from_bytes(not_ok.as_bytes()).is_err());
}
Expand Down Expand Up @@ -66,4 +66,28 @@ test_round_trip!(
540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559,
560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599,

600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619,
620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639,
640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659,
660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679,
680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699,

700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719,
720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739,
740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759,
760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779,
780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799,

800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819,
820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839,
840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859,
860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879,
880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899,

900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919,
920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939,
940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959,
960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979,
980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999,
);