    //! HTTP Status
    //! https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

    const std = @import("../std.zig");

    pub const Status = enum(u10) {
        @"continue" = 100, // RFC7231, Section 6.2.1

        switching_protocols = 101, // RFC7231, Section 6.2.2

        processing = 102, // RFC2518

        early_hints = 103, // RFC8297

        ok = 200, // RFC7231, Section 6.3.1

        created = 201, // RFC7231, Section 6.3.2

        accepted = 202, // RFC7231, Section 6.3.3

        non_authoritative_info = 203, // RFC7231, Section 6.3.4

        no_content = 204, // RFC7231, Section 6.3.5

        reset_content = 205, // RFC7231, Section 6.3.6

        partial_content = 206, // RFC7233, Section 4.1

        multi_status = 207, // RFC4918

        already_reported = 208, // RFC5842

        im_used = 226, // RFC3229

        multiple_choice = 300, // RFC7231, Section 6.4.1

        moved_permanently = 301, // RFC7231, Section 6.4.2

        found = 302, // RFC7231, Section 6.4.3

        see_other = 303, // RFC7231, Section 6.4.4

        not_modified = 304, // RFC7232, Section 4.1

        use_proxy = 305, // RFC7231, Section 6.4.5

        temporary_redirect = 307, // RFC7231, Section 6.4.7

        permanent_redirect = 308, // RFC7538

        bad_request = 400, // RFC7231, Section 6.5.1

        unauthorized = 401, // RFC7235, Section 3.1

        payment_required = 402, // RFC7231, Section 6.5.2

        forbidden = 403, // RFC7231, Section 6.5.3

        not_found = 404, // RFC7231, Section 6.5.4

        method_not_allowed = 405, // RFC7231, Section 6.5.5

        not_acceptable = 406, // RFC7231, Section 6.5.6

        proxy_auth_required = 407, // RFC7235, Section 3.2

        request_timeout = 408, // RFC7231, Section 6.5.7

        conflict = 409, // RFC7231, Section 6.5.8

        gone = 410, // RFC7231, Section 6.5.9

        length_required = 411, // RFC7231, Section 6.5.10

        precondition_failed = 412, // RFC7232, Section 4.2][RFC8144, Section 3.2

        payload_too_large = 413, // RFC7231, Section 6.5.11

        uri_too_long = 414, // RFC7231, Section 6.5.12

        unsupported_media_type = 415, // RFC7231, Section 6.5.13][RFC7694, Section 3

        range_not_satisfiable = 416, // RFC7233, Section 4.4

        expectation_failed = 417, // RFC7231, Section 6.5.14

        teapot = 418, // RFC 7168, 2.3.3

        misdirected_request = 421, // RFC7540, Section 9.1.2

        unprocessable_entity = 422, // RFC4918

        locked = 423, // RFC4918

        failed_dependency = 424, // RFC4918

        too_early = 425, // RFC8470

        upgrade_required = 426, // RFC7231, Section 6.5.15

        precondition_required = 428, // RFC6585

        too_many_requests = 429, // RFC6585

        header_fields_too_large = 431, // RFC6585

        unavailable_for_legal_reasons = 451, // RFC7725

        internal_server_error = 500, // RFC7231, Section 6.6.1

        not_implemented = 501, // RFC7231, Section 6.6.2

        bad_gateway = 502, // RFC7231, Section 6.6.3

        service_unavailable = 503, // RFC7231, Section 6.6.4

        gateway_timeout = 504, // RFC7231, Section 6.6.5

        http_version_not_supported = 505, // RFC7231, Section 6.6.6

        variant_also_negotiates = 506, // RFC2295

        insufficient_storage = 507, // RFC4918

        loop_detected = 508, // RFC5842

        not_extended = 510, // RFC2774

        network_authentication_required = 511, // RFC6585

        _,

        pub fn phrase(self: Status) ?[]const u8 {
            return switch (self) {
                // 1xx statuses

                .@"continue" => "Continue",
                .switching_protocols => "Switching Protocols",
                .processing => "Processing",
                .early_hints => "Early Hints",

                // 2xx statuses

                .ok => "OK",
                .created => "Created",
                .accepted => "Accepted",
                .non_authoritative_info => "Non-Authoritative Information",
                .no_content => "No Content",
                .reset_content => "Reset Content",
                .partial_content => "Partial Content",
                .multi_status => "Multi-Status",
                .already_reported => "Already Reported",
                .im_used => "IM Used",

                // 3xx statuses

                .multiple_choice => "Multiple Choice",
                .moved_permanently => "Moved Permanently",
                .found => "Found",
                .see_other => "See Other",
                .not_modified => "Not Modified",
                .use_proxy => "Use Proxy",
                .temporary_redirect => "Temporary Redirect",
                .permanent_redirect => "Permanent Redirect",

                // 4xx statuses

                .bad_request => "Bad Request",
                .unauthorized => "Unauthorized",
                .payment_required => "Payment Required",
                .forbidden => "Forbidden",
                .not_found => "Not Found",
                .method_not_allowed => "Method Not Allowed",
                .not_acceptable => "Not Acceptable",
                .proxy_auth_required => "Proxy Authentication Required",
                .request_timeout => "Request Timeout",
                .conflict => "Conflict",
                .gone => "Gone",
                .length_required => "Length Required",
                .precondition_failed => "Precondition Failed",
                .payload_too_large => "Payload Too Large",
                .uri_too_long => "URI Too Long",
                .unsupported_media_type => "Unsupported Media Type",
                .range_not_satisfiable => "Range Not Satisfiable",
                .expectation_failed => "Expectation Failed",
                .teapot => "I'm a teapot",
                .misdirected_request => "Misdirected Request",
                .unprocessable_entity => "Unprocessable Entity",
                .locked => "Locked",
                .failed_dependency => "Failed Dependency",
                .too_early => "Too Early",
                .upgrade_required => "Upgrade Required",
                .precondition_required => "Precondition Required",
                .too_many_requests => "Too Many Requests",
                .header_fields_too_large => "Request Header Fields Too Large",
                .unavailable_for_legal_reasons => "Unavailable For Legal Reasons",

                // 5xx statuses

                .internal_server_error => "Internal Server Error",
                .not_implemented => "Not Implemented",
                .bad_gateway => "Bad Gateway",
                .service_unavailable => "Service Unavailable",
                .gateway_timeout => "Gateway Timeout",
                .http_version_not_supported => "HTTP Version Not Supported",
                .variant_also_negotiates => "Variant Also Negotiates",
                .insufficient_storage => "Insufficient Storage",
                .loop_detected => "Loop Detected",
                .not_extended => "Not Extended",
                .network_authentication_required => "Network Authentication Required",

                else => return null,
            };
        }

        pub const Class = enum {
            informational,
            success,
            redirect,
            client_error,
            server_error,
        };

        pub fn class(self: Status) ?Class {
            return switch (@enumToInt(self)) {
                100...199 => .informational,
                200...299 => .success,
                300...399 => .redirect,
                400...499 => .client_error,
                500...599 => .server_error,
                else => null,
            };
        }
    };

    test {
        try std.testing.expectEqualStrings("OK", Status.ok.phrase().?);
        try std.testing.expectEqualStrings("Not Found", Status.not_found.phrase().?);
    }

    test {
        try std.testing.expectEqual(@as(?Status.Class, Status.Class.success), Status.ok.class());
        try std.testing.expectEqual(@as(?Status.Class, Status.Class.client_error), Status.not_found.class());
    }