From 45df4d0d9b577fecee798d672695fe24ff57fb1b Mon Sep 17 00:00:00 2001 From: mo khan Date: Tue, 15 Jul 2025 16:37:08 -0600 Subject: feat: migrate from Cedar to SpiceDB authorization system This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema. --- vendor/http/src/status.rs | 594 ---------------------------------------------- 1 file changed, 594 deletions(-) delete mode 100644 vendor/http/src/status.rs (limited to 'vendor/http/src/status.rs') diff --git a/vendor/http/src/status.rs b/vendor/http/src/status.rs deleted file mode 100644 index 7b3e8d64..00000000 --- a/vendor/http/src/status.rs +++ /dev/null @@ -1,594 +0,0 @@ -//! HTTP status codes -//! -//! This module contains HTTP-status code related structs an errors. The main -//! type in this module is `StatusCode` which is not intended to be used through -//! this module but rather the `http::StatusCode` type. -//! -//! # Examples -//! -//! ``` -//! use http::StatusCode; -//! -//! assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK); -//! assert_eq!(StatusCode::NOT_FOUND, 404); -//! assert!(StatusCode::OK.is_success()); -//! ``` - -use std::convert::TryFrom; -use std::error::Error; -use std::fmt; -use std::num::NonZeroU16; -use std::str::FromStr; - -/// An HTTP status code (`status-code` in RFC 9110 et al.). -/// -/// Constants are provided for known status codes, including those in the IANA -/// [HTTP Status Code Registry]( -/// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml). -/// -/// Status code values in the range 100-999 (inclusive) are supported by this -/// type. Values in the range 100-599 are semantically classified by the most -/// significant digit. See [`StatusCode::is_success`], etc. Values above 599 -/// are unclassified but allowed for legacy compatibility, though their use is -/// discouraged. Applications may interpret such values as protocol errors. -/// -/// # Examples -/// -/// ``` -/// use http::StatusCode; -/// -/// assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK); -/// assert_eq!(StatusCode::NOT_FOUND.as_u16(), 404); -/// assert!(StatusCode::OK.is_success()); -/// ``` -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -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 999. -pub struct InvalidStatusCode { - _priv: (), -} - -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 and less than 1000. - /// - /// # Example - /// - /// ``` - /// use http::StatusCode; - /// - /// let ok = StatusCode::from_u16(200).unwrap(); - /// assert_eq!(ok, StatusCode::OK); - /// - /// let err = StatusCode::from_u16(99); - /// assert!(err.is_err()); - /// ``` - #[inline] - pub fn from_u16(src: u16) -> Result { - if !(100..1000).contains(&src) { - return Err(InvalidStatusCode::new()); - } - - NonZeroU16::new(src) - .map(StatusCode) - .ok_or_else(InvalidStatusCode::new) - } - - /// Converts a `&[u8]` to a status code. - pub fn from_bytes(src: &[u8]) -> Result { - if src.len() != 3 { - return Err(InvalidStatusCode::new()); - } - - let a = src[0].wrapping_sub(b'0') as u16; - let b = src[1].wrapping_sub(b'0') as u16; - let c = src[2].wrapping_sub(b'0') as u16; - - if a == 0 || a > 9 || b > 9 || c > 9 { - return Err(InvalidStatusCode::new()); - } - - let status = (a * 100) + (b * 10) + c; - NonZeroU16::new(status) - .map(StatusCode) - .ok_or_else(InvalidStatusCode::new) - } - - /// Returns the `u16` corresponding to this `StatusCode`. - /// - /// # Note - /// - /// This is the same as the `From` implementation, but - /// included as an inherent method because that implementation doesn't - /// appear in rustdocs, as well as a way to force the type instead of - /// relying on inference. - /// - /// # Example - /// - /// ``` - /// let status = http::StatusCode::OK; - /// assert_eq!(status.as_u16(), 200); - /// ``` - #[inline] - pub const fn as_u16(&self) -> u16 { - self.0.get() - } - - /// Returns a &str representation of the `StatusCode` - /// - /// The return value only includes a numerical representation of the - /// status code. The canonical reason is not included. - /// - /// # Example - /// - /// ``` - /// let status = http::StatusCode::OK; - /// assert_eq!(status.as_str(), "200"); - /// ``` - #[inline] - pub fn as_str(&self) -> &str { - let offset = (self.0.get() - 100) as usize; - let offset = offset * 3; - - // Invariant: self has checked range [100, 999] and CODE_DIGITS is - // ASCII-only, of length 900 * 3 = 2700 bytes - - #[cfg(debug_assertions)] - { - &CODE_DIGITS[offset..offset + 3] - } - - #[cfg(not(debug_assertions))] - unsafe { - CODE_DIGITS.get_unchecked(offset..offset + 3) - } - } - - /// Get the standardised `reason-phrase` for this status code. - /// - /// This is mostly here for servers writing responses, but could potentially have application - /// at other times. - /// - /// The reason phrase is defined as being exclusively for human readers. You should avoid - /// deriving any meaning from it at all costs. - /// - /// Bear in mind also that in HTTP/2.0 and HTTP/3.0 the reason phrase is abolished from - /// transmission, and so this canonical reason phrase really is the only reason phrase you’ll - /// find. - /// - /// # Example - /// - /// ``` - /// let status = http::StatusCode::OK; - /// assert_eq!(status.canonical_reason(), Some("OK")); - /// ``` - pub fn canonical_reason(&self) -> Option<&'static str> { - canonical_reason(self.0.get()) - } - - /// Check if status is within 100-199. - #[inline] - pub fn is_informational(&self) -> bool { - (100..200).contains(&self.0.get()) - } - - /// Check if status is within 200-299. - #[inline] - pub fn is_success(&self) -> bool { - (200..300).contains(&self.0.get()) - } - - /// Check if status is within 300-399. - #[inline] - pub fn is_redirection(&self) -> bool { - (300..400).contains(&self.0.get()) - } - - /// Check if status is within 400-499. - #[inline] - pub fn is_client_error(&self) -> bool { - (400..500).contains(&self.0.get()) - } - - /// Check if status is within 500-599. - #[inline] - pub fn is_server_error(&self) -> bool { - (500..600).contains(&self.0.get()) - } -} - -impl fmt::Debug for StatusCode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.0, f) - } -} - -/// Formats the status code, *including* the canonical reason. -/// -/// # Example -/// -/// ``` -/// # use http::StatusCode; -/// assert_eq!(format!("{}", StatusCode::OK), "200 OK"); -/// ``` -impl fmt::Display for StatusCode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{} {}", - u16::from(*self), - self.canonical_reason().unwrap_or("") - ) - } -} - -impl Default for StatusCode { - #[inline] - fn default() -> StatusCode { - StatusCode::OK - } -} - -impl PartialEq for StatusCode { - #[inline] - fn eq(&self, other: &u16) -> bool { - self.as_u16() == *other - } -} - -impl PartialEq for u16 { - #[inline] - fn eq(&self, other: &StatusCode) -> bool { - *self == other.as_u16() - } -} - -impl From for u16 { - #[inline] - fn from(status: StatusCode) -> u16 { - status.0.get() - } -} - -impl FromStr for StatusCode { - type Err = InvalidStatusCode; - - fn from_str(s: &str) -> Result { - StatusCode::from_bytes(s.as_ref()) - } -} - -impl<'a> From<&'a StatusCode> for StatusCode { - #[inline] - fn from(t: &'a StatusCode) -> Self { - t.to_owned() - } -} - -impl<'a> TryFrom<&'a [u8]> for StatusCode { - type Error = InvalidStatusCode; - - #[inline] - fn try_from(t: &'a [u8]) -> Result { - StatusCode::from_bytes(t) - } -} - -impl<'a> TryFrom<&'a str> for StatusCode { - type Error = InvalidStatusCode; - - #[inline] - fn try_from(t: &'a str) -> Result { - t.parse() - } -} - -impl TryFrom for StatusCode { - type Error = InvalidStatusCode; - - #[inline] - fn try_from(t: u16) -> Result { - StatusCode::from_u16(t) - } -} - -macro_rules! status_codes { - ( - $( - $(#[$docs:meta])* - ($num:expr, $konst:ident, $phrase:expr); - )+ - ) => { - impl StatusCode { - $( - $(#[$docs])* - pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) }); - )+ - - } - - fn canonical_reason(num: u16) -> Option<&'static str> { - match num { - $( - $num => Some($phrase), - )+ - _ => None - } - } - } -} - -status_codes! { - /// 100 Continue - /// [[RFC9110, Section 15.2.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.2.1)] - (100, CONTINUE, "Continue"); - /// 101 Switching Protocols - /// [[RFC9110, Section 15.2.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.2.2)] - (101, SWITCHING_PROTOCOLS, "Switching Protocols"); - /// 102 Processing - /// [[RFC2518, Section 10.1](https://datatracker.ietf.org/doc/html/rfc2518#section-10.1)] - (102, PROCESSING, "Processing"); - - /// 200 OK - /// [[RFC9110, Section 15.3.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.1)] - (200, OK, "OK"); - /// 201 Created - /// [[RFC9110, Section 15.3.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.2)] - (201, CREATED, "Created"); - /// 202 Accepted - /// [[RFC9110, Section 15.3.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.3)] - (202, ACCEPTED, "Accepted"); - /// 203 Non-Authoritative Information - /// [[RFC9110, Section 15.3.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.4)] - (203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information"); - /// 204 No Content - /// [[RFC9110, Section 15.3.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.5)] - (204, NO_CONTENT, "No Content"); - /// 205 Reset Content - /// [[RFC9110, Section 15.3.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.6)] - (205, RESET_CONTENT, "Reset Content"); - /// 206 Partial Content - /// [[RFC9110, Section 15.3.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.3.7)] - (206, PARTIAL_CONTENT, "Partial Content"); - /// 207 Multi-Status - /// [[RFC4918, Section 11.1](https://datatracker.ietf.org/doc/html/rfc4918#section-11.1)] - (207, MULTI_STATUS, "Multi-Status"); - /// 208 Already Reported - /// [[RFC5842, Section 7.1](https://datatracker.ietf.org/doc/html/rfc5842#section-7.1)] - (208, ALREADY_REPORTED, "Already Reported"); - - /// 226 IM Used - /// [[RFC3229, Section 10.4.1](https://datatracker.ietf.org/doc/html/rfc3229#section-10.4.1)] - (226, IM_USED, "IM Used"); - - /// 300 Multiple Choices - /// [[RFC9110, Section 15.4.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.1)] - (300, MULTIPLE_CHOICES, "Multiple Choices"); - /// 301 Moved Permanently - /// [[RFC9110, Section 15.4.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2)] - (301, MOVED_PERMANENTLY, "Moved Permanently"); - /// 302 Found - /// [[RFC9110, Section 15.4.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.3)] - (302, FOUND, "Found"); - /// 303 See Other - /// [[RFC9110, Section 15.4.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.4)] - (303, SEE_OTHER, "See Other"); - /// 304 Not Modified - /// [[RFC9110, Section 15.4.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.5)] - (304, NOT_MODIFIED, "Not Modified"); - /// 305 Use Proxy - /// [[RFC9110, Section 15.4.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.6)] - (305, USE_PROXY, "Use Proxy"); - /// 307 Temporary Redirect - /// [[RFC9110, Section 15.4.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.7)] - (307, TEMPORARY_REDIRECT, "Temporary Redirect"); - /// 308 Permanent Redirect - /// [[RFC9110, Section 15.4.8](https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.8)] - (308, PERMANENT_REDIRECT, "Permanent Redirect"); - - /// 400 Bad Request - /// [[RFC9110, Section 15.5.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.1)] - (400, BAD_REQUEST, "Bad Request"); - /// 401 Unauthorized - /// [[RFC9110, Section 15.5.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.2)] - (401, UNAUTHORIZED, "Unauthorized"); - /// 402 Payment Required - /// [[RFC9110, Section 15.5.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.3)] - (402, PAYMENT_REQUIRED, "Payment Required"); - /// 403 Forbidden - /// [[RFC9110, Section 15.5.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.4)] - (403, FORBIDDEN, "Forbidden"); - /// 404 Not Found - /// [[RFC9110, Section 15.5.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.5)] - (404, NOT_FOUND, "Not Found"); - /// 405 Method Not Allowed - /// [[RFC9110, Section 15.5.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.6)] - (405, METHOD_NOT_ALLOWED, "Method Not Allowed"); - /// 406 Not Acceptable - /// [[RFC9110, Section 15.5.7](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.7)] - (406, NOT_ACCEPTABLE, "Not Acceptable"); - /// 407 Proxy Authentication Required - /// [[RFC9110, Section 15.5.8](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.8)] - (407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required"); - /// 408 Request Timeout - /// [[RFC9110, Section 15.5.9](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.9)] - (408, REQUEST_TIMEOUT, "Request Timeout"); - /// 409 Conflict - /// [[RFC9110, Section 15.5.10](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.10)] - (409, CONFLICT, "Conflict"); - /// 410 Gone - /// [[RFC9110, Section 15.5.11](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.11)] - (410, GONE, "Gone"); - /// 411 Length Required - /// [[RFC9110, Section 15.5.12](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.12)] - (411, LENGTH_REQUIRED, "Length Required"); - /// 412 Precondition Failed - /// [[RFC9110, Section 15.5.13](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.13)] - (412, PRECONDITION_FAILED, "Precondition Failed"); - /// 413 Payload Too Large - /// [[RFC9110, Section 15.5.14](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.14)] - (413, PAYLOAD_TOO_LARGE, "Payload Too Large"); - /// 414 URI Too Long - /// [[RFC9110, Section 15.5.15](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.15)] - (414, URI_TOO_LONG, "URI Too Long"); - /// 415 Unsupported Media Type - /// [[RFC9110, Section 15.5.16](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.16)] - (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type"); - /// 416 Range Not Satisfiable - /// [[RFC9110, Section 15.5.17](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.17)] - (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable"); - /// 417 Expectation Failed - /// [[RFC9110, Section 15.5.18](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.18)] - (417, EXPECTATION_FAILED, "Expectation Failed"); - /// 418 I'm a teapot - /// [curiously not registered by IANA but [RFC2324, Section 2.3.2](https://datatracker.ietf.org/doc/html/rfc2324#section-2.3.2)] - (418, IM_A_TEAPOT, "I'm a teapot"); - - /// 421 Misdirected Request - /// [[RFC9110, Section 15.5.20](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.20)] - (421, MISDIRECTED_REQUEST, "Misdirected Request"); - /// 422 Unprocessable Entity - /// [[RFC9110, Section 15.5.21](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.21)] - (422, UNPROCESSABLE_ENTITY, "Unprocessable Entity"); - /// 423 Locked - /// [[RFC4918, Section 11.3](https://datatracker.ietf.org/doc/html/rfc4918#section-11.3)] - (423, LOCKED, "Locked"); - /// 424 Failed Dependency - /// [[RFC4918, Section 11.4](https://tools.ietf.org/html/rfc4918#section-11.4)] - (424, FAILED_DEPENDENCY, "Failed Dependency"); - - /// 425 Too early - /// [[RFC8470, Section 5.2](https://httpwg.org/specs/rfc8470.html#status)] - (425, TOO_EARLY, "Too Early"); - - /// 426 Upgrade Required - /// [[RFC9110, Section 15.5.22](https://datatracker.ietf.org/doc/html/rfc9110#section-15.5.22)] - (426, UPGRADE_REQUIRED, "Upgrade Required"); - - /// 428 Precondition Required - /// [[RFC6585, Section 3](https://datatracker.ietf.org/doc/html/rfc6585#section-3)] - (428, PRECONDITION_REQUIRED, "Precondition Required"); - /// 429 Too Many Requests - /// [[RFC6585, Section 4](https://datatracker.ietf.org/doc/html/rfc6585#section-4)] - (429, TOO_MANY_REQUESTS, "Too Many Requests"); - - /// 431 Request Header Fields Too Large - /// [[RFC6585, Section 5](https://datatracker.ietf.org/doc/html/rfc6585#section-5)] - (431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large"); - - /// 451 Unavailable For Legal Reasons - /// [[RFC7725, Section 3](https://tools.ietf.org/html/rfc7725#section-3)] - (451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons"); - - /// 500 Internal Server Error - /// [[RFC9110, Section 15.6.1](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.1)] - (500, INTERNAL_SERVER_ERROR, "Internal Server Error"); - /// 501 Not Implemented - /// [[RFC9110, Section 15.6.2](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.2)] - (501, NOT_IMPLEMENTED, "Not Implemented"); - /// 502 Bad Gateway - /// [[RFC9110, Section 15.6.3](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.3)] - (502, BAD_GATEWAY, "Bad Gateway"); - /// 503 Service Unavailable - /// [[RFC9110, Section 15.6.4](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.4)] - (503, SERVICE_UNAVAILABLE, "Service Unavailable"); - /// 504 Gateway Timeout - /// [[RFC9110, Section 15.6.5](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.5)] - (504, GATEWAY_TIMEOUT, "Gateway Timeout"); - /// 505 HTTP Version Not Supported - /// [[RFC9110, Section 15.6.6](https://datatracker.ietf.org/doc/html/rfc9110#section-15.6.6)] - (505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported"); - /// 506 Variant Also Negotiates - /// [[RFC2295, Section 8.1](https://datatracker.ietf.org/doc/html/rfc2295#section-8.1)] - (506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates"); - /// 507 Insufficient Storage - /// [[RFC4918, Section 11.5](https://datatracker.ietf.org/doc/html/rfc4918#section-11.5)] - (507, INSUFFICIENT_STORAGE, "Insufficient Storage"); - /// 508 Loop Detected - /// [[RFC5842, Section 7.2](https://datatracker.ietf.org/doc/html/rfc5842#section-7.2)] - (508, LOOP_DETECTED, "Loop Detected"); - - /// 510 Not Extended - /// [[RFC2774, Section 7](https://datatracker.ietf.org/doc/html/rfc2774#section-7)] - (510, NOT_EXTENDED, "Not Extended"); - /// 511 Network Authentication Required - /// [[RFC6585, Section 6](https://datatracker.ietf.org/doc/html/rfc6585#section-6)] - (511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required"); -} - -impl InvalidStatusCode { - fn new() -> InvalidStatusCode { - InvalidStatusCode { _priv: () } - } -} - -impl fmt::Debug for InvalidStatusCode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("InvalidStatusCode") - // skip _priv noise - .finish() - } -} - -impl fmt::Display for InvalidStatusCode { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("invalid status code") - } -} - -impl Error for InvalidStatusCode {} - -// A string of packed 3-ASCII-digit status code values for the supported range -// of [100, 999] (900 codes, 2700 bytes). -const CODE_DIGITS: &str = "\ -100101102103104105106107108109110111112113114115116117118119\ -120121122123124125126127128129130131132133134135136137138139\ -140141142143144145146147148149150151152153154155156157158159\ -160161162163164165166167168169170171172173174175176177178179\ -180181182183184185186187188189190191192193194195196197198199\ -200201202203204205206207208209210211212213214215216217218219\ -220221222223224225226227228229230231232233234235236237238239\ -240241242243244245246247248249250251252253254255256257258259\ -260261262263264265266267268269270271272273274275276277278279\ -280281282283284285286287288289290291292293294295296297298299\ -300301302303304305306307308309310311312313314315316317318319\ -320321322323324325326327328329330331332333334335336337338339\ -340341342343344345346347348349350351352353354355356357358359\ -360361362363364365366367368369370371372373374375376377378379\ -380381382383384385386387388389390391392393394395396397398399\ -400401402403404405406407408409410411412413414415416417418419\ -420421422423424425426427428429430431432433434435436437438439\ -440441442443444445446447448449450451452453454455456457458459\ -460461462463464465466467468469470471472473474475476477478479\ -480481482483484485486487488489490491492493494495496497498499\ -500501502503504505506507508509510511512513514515516517518519\ -520521522523524525526527528529530531532533534535536537538539\ -540541542543544545546547548549550551552553554555556557558559\ -560561562563564565566567568569570571572573574575576577578579\ -580581582583584585586587588589590591592593594595596597598599\ -600601602603604605606607608609610611612613614615616617618619\ -620621622623624625626627628629630631632633634635636637638639\ -640641642643644645646647648649650651652653654655656657658659\ -660661662663664665666667668669670671672673674675676677678679\ -680681682683684685686687688689690691692693694695696697698699\ -700701702703704705706707708709710711712713714715716717718719\ -720721722723724725726727728729730731732733734735736737738739\ -740741742743744745746747748749750751752753754755756757758759\ -760761762763764765766767768769770771772773774775776777778779\ -780781782783784785786787788789790791792793794795796797798799\ -800801802803804805806807808809810811812813814815816817818819\ -820821822823824825826827828829830831832833834835836837838839\ -840841842843844845846847848849850851852853854855856857858859\ -860861862863864865866867868869870871872873874875876877878879\ -880881882883884885886887888889890891892893894895896897898899\ -900901902903904905906907908909910911912913914915916917918919\ -920921922923924925926927928929930931932933934935936937938939\ -940941942943944945946947948949950951952953954955956957958959\ -960961962963964965966967968969970971972973974975976977978979\ -980981982983984985986987988989990991992993994995996997998999"; -- cgit v1.2.3