no_std_http/
status.rs

1//! HTTP status codes
2//!
3//! This module contains HTTP-status code related structs an errors. The main
4//! type in this module is `StatusCode` which is not intended to be used through
5//! this module but rather the `http::StatusCode` type.
6//!
7//! # Examples
8//!
9//! ```
10//! use http::StatusCode;
11//!
12//! assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK);
13//! assert_eq!(StatusCode::NOT_FOUND, 404);
14//! assert!(StatusCode::OK.is_success());
15//! ```
16
17use crate::error::{Error, Result};
18use core::convert::TryFrom;
19use core::fmt;
20use core::num::NonZeroU16;
21use core::str::FromStr;
22
23/// An HTTP status code (`status-code` in RFC 7230 et al.).
24///
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).
28///
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.
34///
35/// # Examples
36///
37/// ```
38/// use http::StatusCode;
39///
40/// assert_eq!(StatusCode::from_u16(200).unwrap(), StatusCode::OK);
41/// assert_eq!(StatusCode::NOT_FOUND.as_u16(), 404);
42/// assert!(StatusCode::OK.is_success());
43/// ```
44#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
45pub struct StatusCode(NonZeroU16);
46
47impl StatusCode {
48    /// Converts a u16 to a status code.
49    ///
50    /// The function validates the correctness of the supplied u16. It must be
51    /// greater or equal to 100 and less than 1000.
52    ///
53    /// # Example
54    ///
55    /// ```
56    /// use http::StatusCode;
57    ///
58    /// let ok = StatusCode::from_u16(200).unwrap();
59    /// assert_eq!(ok, StatusCode::OK);
60    ///
61    /// let err = StatusCode::from_u16(99);
62    /// assert!(err.is_err());
63    /// ```
64    #[inline]
65    pub fn from_u16(src: u16) -> Result<StatusCode> {
66        if !(100..1000).contains(&src) {
67            return Err(Error::InvalidStatusCode);
68        }
69
70        NonZeroU16::new(src)
71            .map(StatusCode)
72            .ok_or(Error::InvalidStatusCode)
73    }
74
75    /// Converts a &[u8] to a status code
76    pub fn from_bytes(src: &[u8]) -> Result<StatusCode> {
77        if src.len() != 3 {
78            return Err(Error::InvalidStatusCode);
79        }
80
81        let a = src[0].wrapping_sub(b'0') as u16;
82        let b = src[1].wrapping_sub(b'0') as u16;
83        let c = src[2].wrapping_sub(b'0') as u16;
84
85        if a == 0 || a > 9 || b > 9 || c > 9 {
86            return Err(Error::InvalidStatusCode);
87        }
88
89        let status = (a * 100) + (b * 10) + c;
90        NonZeroU16::new(status)
91            .map(StatusCode)
92            .ok_or(Error::InvalidStatusCode)
93    }
94
95    /// Returns the `u16` corresponding to this `StatusCode`.
96    ///
97    /// # Note
98    ///
99    /// This is the same as the `From<StatusCode>` implementation, but
100    /// included as an inherent method because that implementation doesn't
101    /// appear in rustdocs, as well as a way to force the type instead of
102    /// relying on inference.
103    ///
104    /// # Example
105    ///
106    /// ```
107    /// let status = http::StatusCode::OK;
108    /// assert_eq!(status.as_u16(), 200);
109    /// ```
110    #[inline]
111    pub fn as_u16(&self) -> u16 {
112        (*self).into()
113    }
114
115    /// Returns a &str representation of the `StatusCode`
116    ///
117    /// The return value only includes a numerical representation of the
118    /// status code. The canonical reason is not included.
119    ///
120    /// # Example
121    ///
122    /// ```
123    /// let status = http::StatusCode::OK;
124    /// assert_eq!(status.as_str(), "200");
125    /// ```
126    #[inline]
127    pub fn as_str(&self) -> &str {
128        let offset = (self.0.get() - 100) as usize;
129        let offset = offset * 3;
130
131        // Invariant: self has checked range [100, 999] and CODE_DIGITS is
132        // ASCII-only, of length 900 * 3 = 2700 bytes
133
134        #[cfg(debug_assertions)]
135        {
136            &CODE_DIGITS[offset..offset + 3]
137        }
138
139        #[cfg(not(debug_assertions))]
140        unsafe {
141            CODE_DIGITS.get_unchecked(offset..offset + 3)
142        }
143    }
144
145    /// Get the standardised `reason-phrase` for this status code.
146    ///
147    /// This is mostly here for servers writing responses, but could potentially have application
148    /// at other times.
149    ///
150    /// The reason phrase is defined as being exclusively for human readers. You should avoid
151    /// deriving any meaning from it at all costs.
152    ///
153    /// Bear in mind also that in HTTP/2.0 and HTTP/3.0 the reason phrase is abolished from
154    /// transmission, and so this canonical reason phrase really is the only reason phrase you’ll
155    /// find.
156    ///
157    /// # Example
158    ///
159    /// ```
160    /// let status = http::StatusCode::OK;
161    /// assert_eq!(status.canonical_reason(), Some("OK"));
162    /// ```
163    pub fn canonical_reason(&self) -> Option<&'static str> {
164        canonical_reason(self.0.get())
165    }
166
167    /// Check if status is within 100-199.
168    #[inline]
169    pub fn is_informational(&self) -> bool {
170        200 > self.0.get() && self.0.get() >= 100
171    }
172
173    /// Check if status is within 200-299.
174    #[inline]
175    pub fn is_success(&self) -> bool {
176        300 > self.0.get() && self.0.get() >= 200
177    }
178
179    /// Check if status is within 300-399.
180    #[inline]
181    pub fn is_redirection(&self) -> bool {
182        400 > self.0.get() && self.0.get() >= 300
183    }
184
185    /// Check if status is within 400-499.
186    #[inline]
187    pub fn is_client_error(&self) -> bool {
188        500 > self.0.get() && self.0.get() >= 400
189    }
190
191    /// Check if status is within 500-599.
192    #[inline]
193    pub fn is_server_error(&self) -> bool {
194        600 > self.0.get() && self.0.get() >= 500
195    }
196}
197
198impl fmt::Debug for StatusCode {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        fmt::Debug::fmt(&self.0, f)
201    }
202}
203
204/// Formats the status code, *including* the canonical reason.
205///
206/// # Example
207///
208/// ```
209/// # use http::StatusCode;
210/// assert_eq!(format!("{}", StatusCode::OK), "200 OK");
211/// ```
212impl fmt::Display for StatusCode {
213    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214        write!(
215            f,
216            "{} {}",
217            u16::from(*self),
218            self.canonical_reason().unwrap_or("<unknown status code>")
219        )
220    }
221}
222
223impl Default for StatusCode {
224    #[inline]
225    fn default() -> StatusCode {
226        StatusCode::OK
227    }
228}
229
230impl PartialEq<u16> for StatusCode {
231    #[inline]
232    fn eq(&self, other: &u16) -> bool {
233        self.as_u16() == *other
234    }
235}
236
237impl PartialEq<StatusCode> for u16 {
238    #[inline]
239    fn eq(&self, other: &StatusCode) -> bool {
240        *self == other.as_u16()
241    }
242}
243
244impl From<StatusCode> for u16 {
245    #[inline]
246    fn from(status: StatusCode) -> u16 {
247        status.0.get()
248    }
249}
250
251impl FromStr for StatusCode {
252    type Err = Error;
253
254    fn from_str(s: &str) -> Result<StatusCode> {
255        StatusCode::from_bytes(s.as_ref())
256    }
257}
258
259impl<'a> From<&'a StatusCode> for StatusCode {
260    #[inline]
261    fn from(t: &'a StatusCode) -> Self {
262        *t
263    }
264}
265
266impl<'a> TryFrom<&'a [u8]> for StatusCode {
267    type Error = Error;
268
269    #[inline]
270    fn try_from(t: &'a [u8]) -> Result<Self> {
271        StatusCode::from_bytes(t)
272    }
273}
274
275impl<'a> TryFrom<&'a str> for StatusCode {
276    type Error = Error;
277
278    #[inline]
279    fn try_from(t: &'a str) -> Result<Self> {
280        t.parse()
281    }
282}
283
284impl TryFrom<u16> for StatusCode {
285    type Error = Error;
286
287    #[inline]
288    fn try_from(t: u16) -> Result<Self> {
289        StatusCode::from_u16(t)
290    }
291}
292
293macro_rules! status_codes {
294    (
295        $(
296            $(#[$docs:meta])*
297            ($num:expr, $konst:ident, $phrase:expr);
298        )+
299    ) => {
300        impl StatusCode {
301        $(
302            $(#[$docs])*
303            pub const $konst: StatusCode = StatusCode(unsafe { NonZeroU16::new_unchecked($num) });
304        )+
305
306        }
307
308        fn canonical_reason(num: u16) -> Option<&'static str> {
309            match num {
310                $(
311                $num => Some($phrase),
312                )+
313                _ => None
314            }
315        }
316    }
317}
318
319status_codes! {
320    /// 100 Continue
321    /// [[RFC7231, Section 6.2.1](https://tools.ietf.org/html/rfc7231#section-6.2.1)]
322    (100, CONTINUE, "Continue");
323    /// 101 Switching Protocols
324    /// [[RFC7231, Section 6.2.2](https://tools.ietf.org/html/rfc7231#section-6.2.2)]
325    (101, SWITCHING_PROTOCOLS, "Switching Protocols");
326    /// 102 Processing
327    /// [[RFC2518](https://tools.ietf.org/html/rfc2518)]
328    (102, PROCESSING, "Processing");
329
330    /// 200 OK
331    /// [[RFC7231, Section 6.3.1](https://tools.ietf.org/html/rfc7231#section-6.3.1)]
332    (200, OK, "OK");
333    /// 201 Created
334    /// [[RFC7231, Section 6.3.2](https://tools.ietf.org/html/rfc7231#section-6.3.2)]
335    (201, CREATED, "Created");
336    /// 202 Accepted
337    /// [[RFC7231, Section 6.3.3](https://tools.ietf.org/html/rfc7231#section-6.3.3)]
338    (202, ACCEPTED, "Accepted");
339    /// 203 Non-Authoritative Information
340    /// [[RFC7231, Section 6.3.4](https://tools.ietf.org/html/rfc7231#section-6.3.4)]
341    (203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information");
342    /// 204 No Content
343    /// [[RFC7231, Section 6.3.5](https://tools.ietf.org/html/rfc7231#section-6.3.5)]
344    (204, NO_CONTENT, "No Content");
345    /// 205 Reset Content
346    /// [[RFC7231, Section 6.3.6](https://tools.ietf.org/html/rfc7231#section-6.3.6)]
347    (205, RESET_CONTENT, "Reset Content");
348    /// 206 Partial Content
349    /// [[RFC7233, Section 4.1](https://tools.ietf.org/html/rfc7233#section-4.1)]
350    (206, PARTIAL_CONTENT, "Partial Content");
351    /// 207 Multi-Status
352    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
353    (207, MULTI_STATUS, "Multi-Status");
354    /// 208 Already Reported
355    /// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
356    (208, ALREADY_REPORTED, "Already Reported");
357
358    /// 226 IM Used
359    /// [[RFC3229](https://tools.ietf.org/html/rfc3229)]
360    (226, IM_USED, "IM Used");
361
362    /// 300 Multiple Choices
363    /// [[RFC7231, Section 6.4.1](https://tools.ietf.org/html/rfc7231#section-6.4.1)]
364    (300, MULTIPLE_CHOICES, "Multiple Choices");
365    /// 301 Moved Permanently
366    /// [[RFC7231, Section 6.4.2](https://tools.ietf.org/html/rfc7231#section-6.4.2)]
367    (301, MOVED_PERMANENTLY, "Moved Permanently");
368    /// 302 Found
369    /// [[RFC7231, Section 6.4.3](https://tools.ietf.org/html/rfc7231#section-6.4.3)]
370    (302, FOUND, "Found");
371    /// 303 See Other
372    /// [[RFC7231, Section 6.4.4](https://tools.ietf.org/html/rfc7231#section-6.4.4)]
373    (303, SEE_OTHER, "See Other");
374    /// 304 Not Modified
375    /// [[RFC7232, Section 4.1](https://tools.ietf.org/html/rfc7232#section-4.1)]
376    (304, NOT_MODIFIED, "Not Modified");
377    /// 305 Use Proxy
378    /// [[RFC7231, Section 6.4.5](https://tools.ietf.org/html/rfc7231#section-6.4.5)]
379    (305, USE_PROXY, "Use Proxy");
380    /// 307 Temporary Redirect
381    /// [[RFC7231, Section 6.4.7](https://tools.ietf.org/html/rfc7231#section-6.4.7)]
382    (307, TEMPORARY_REDIRECT, "Temporary Redirect");
383    /// 308 Permanent Redirect
384    /// [[RFC7238](https://tools.ietf.org/html/rfc7238)]
385    (308, PERMANENT_REDIRECT, "Permanent Redirect");
386
387    /// 400 Bad Request
388    /// [[RFC7231, Section 6.5.1](https://tools.ietf.org/html/rfc7231#section-6.5.1)]
389    (400, BAD_REQUEST, "Bad Request");
390    /// 401 Unauthorized
391    /// [[RFC7235, Section 3.1](https://tools.ietf.org/html/rfc7235#section-3.1)]
392    (401, UNAUTHORIZED, "Unauthorized");
393    /// 402 Payment Required
394    /// [[RFC7231, Section 6.5.2](https://tools.ietf.org/html/rfc7231#section-6.5.2)]
395    (402, PAYMENT_REQUIRED, "Payment Required");
396    /// 403 Forbidden
397    /// [[RFC7231, Section 6.5.3](https://tools.ietf.org/html/rfc7231#section-6.5.3)]
398    (403, FORBIDDEN, "Forbidden");
399    /// 404 Not Found
400    /// [[RFC7231, Section 6.5.4](https://tools.ietf.org/html/rfc7231#section-6.5.4)]
401    (404, NOT_FOUND, "Not Found");
402    /// 405 Method Not Allowed
403    /// [[RFC7231, Section 6.5.5](https://tools.ietf.org/html/rfc7231#section-6.5.5)]
404    (405, METHOD_NOT_ALLOWED, "Method Not Allowed");
405    /// 406 Not Acceptable
406    /// [[RFC7231, Section 6.5.6](https://tools.ietf.org/html/rfc7231#section-6.5.6)]
407    (406, NOT_ACCEPTABLE, "Not Acceptable");
408    /// 407 Proxy Authentication Required
409    /// [[RFC7235, Section 3.2](https://tools.ietf.org/html/rfc7235#section-3.2)]
410    (407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
411    /// 408 Request Timeout
412    /// [[RFC7231, Section 6.5.7](https://tools.ietf.org/html/rfc7231#section-6.5.7)]
413    (408, REQUEST_TIMEOUT, "Request Timeout");
414    /// 409 Conflict
415    /// [[RFC7231, Section 6.5.8](https://tools.ietf.org/html/rfc7231#section-6.5.8)]
416    (409, CONFLICT, "Conflict");
417    /// 410 Gone
418    /// [[RFC7231, Section 6.5.9](https://tools.ietf.org/html/rfc7231#section-6.5.9)]
419    (410, GONE, "Gone");
420    /// 411 Length Required
421    /// [[RFC7231, Section 6.5.10](https://tools.ietf.org/html/rfc7231#section-6.5.10)]
422    (411, LENGTH_REQUIRED, "Length Required");
423    /// 412 Precondition Failed
424    /// [[RFC7232, Section 4.2](https://tools.ietf.org/html/rfc7232#section-4.2)]
425    (412, PRECONDITION_FAILED, "Precondition Failed");
426    /// 413 Payload Too Large
427    /// [[RFC7231, Section 6.5.11](https://tools.ietf.org/html/rfc7231#section-6.5.11)]
428    (413, PAYLOAD_TOO_LARGE, "Payload Too Large");
429    /// 414 URI Too Long
430    /// [[RFC7231, Section 6.5.12](https://tools.ietf.org/html/rfc7231#section-6.5.12)]
431    (414, URI_TOO_LONG, "URI Too Long");
432    /// 415 Unsupported Media Type
433    /// [[RFC7231, Section 6.5.13](https://tools.ietf.org/html/rfc7231#section-6.5.13)]
434    (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
435    /// 416 Range Not Satisfiable
436    /// [[RFC7233, Section 4.4](https://tools.ietf.org/html/rfc7233#section-4.4)]
437    (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable");
438    /// 417 Expectation Failed
439    /// [[RFC7231, Section 6.5.14](https://tools.ietf.org/html/rfc7231#section-6.5.14)]
440    (417, EXPECTATION_FAILED, "Expectation Failed");
441    /// 418 I'm a teapot
442    /// [curiously not registered by IANA but [RFC2324](https://tools.ietf.org/html/rfc2324)]
443    (418, IM_A_TEAPOT, "I'm a teapot");
444
445    /// 421 Misdirected Request
446    /// [RFC7540, Section 9.1.2](https://tools.ietf.org/html/rfc7540#section-9.1.2)
447    (421, MISDIRECTED_REQUEST, "Misdirected Request");
448    /// 422 Unprocessable Entity
449    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
450    (422, UNPROCESSABLE_ENTITY, "Unprocessable Entity");
451    /// 423 Locked
452    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
453    (423, LOCKED, "Locked");
454    /// 424 Failed Dependency
455    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
456    (424, FAILED_DEPENDENCY, "Failed Dependency");
457
458    /// 426 Upgrade Required
459    /// [[RFC7231, Section 6.5.15](https://tools.ietf.org/html/rfc7231#section-6.5.15)]
460    (426, UPGRADE_REQUIRED, "Upgrade Required");
461
462    /// 428 Precondition Required
463    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
464    (428, PRECONDITION_REQUIRED, "Precondition Required");
465    /// 429 Too Many Requests
466    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
467    (429, TOO_MANY_REQUESTS, "Too Many Requests");
468
469    /// 431 Request Header Fields Too Large
470    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
471    (431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large");
472
473    /// 451 Unavailable For Legal Reasons
474    /// [[RFC7725](https://tools.ietf.org/html/rfc7725)]
475    (451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons");
476
477    /// 500 Internal Server Error
478    /// [[RFC7231, Section 6.6.1](https://tools.ietf.org/html/rfc7231#section-6.6.1)]
479    (500, INTERNAL_SERVER_ERROR, "Internal Server Error");
480    /// 501 Not Implemented
481    /// [[RFC7231, Section 6.6.2](https://tools.ietf.org/html/rfc7231#section-6.6.2)]
482    (501, NOT_IMPLEMENTED, "Not Implemented");
483    /// 502 Bad Gateway
484    /// [[RFC7231, Section 6.6.3](https://tools.ietf.org/html/rfc7231#section-6.6.3)]
485    (502, BAD_GATEWAY, "Bad Gateway");
486    /// 503 Service Unavailable
487    /// [[RFC7231, Section 6.6.4](https://tools.ietf.org/html/rfc7231#section-6.6.4)]
488    (503, SERVICE_UNAVAILABLE, "Service Unavailable");
489    /// 504 Gateway Timeout
490    /// [[RFC7231, Section 6.6.5](https://tools.ietf.org/html/rfc7231#section-6.6.5)]
491    (504, GATEWAY_TIMEOUT, "Gateway Timeout");
492    /// 505 HTTP Version Not Supported
493    /// [[RFC7231, Section 6.6.6](https://tools.ietf.org/html/rfc7231#section-6.6.6)]
494    (505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");
495    /// 506 Variant Also Negotiates
496    /// [[RFC2295](https://tools.ietf.org/html/rfc2295)]
497    (506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates");
498    /// 507 Insufficient Storage
499    /// [[RFC4918](https://tools.ietf.org/html/rfc4918)]
500    (507, INSUFFICIENT_STORAGE, "Insufficient Storage");
501    /// 508 Loop Detected
502    /// [[RFC5842](https://tools.ietf.org/html/rfc5842)]
503    (508, LOOP_DETECTED, "Loop Detected");
504
505    /// 510 Not Extended
506    /// [[RFC2774](https://tools.ietf.org/html/rfc2774)]
507    (510, NOT_EXTENDED, "Not Extended");
508    /// 511 Network Authentication Required
509    /// [[RFC6585](https://tools.ietf.org/html/rfc6585)]
510    (511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required");
511}
512
513// A string of packed 3-ASCII-digit status code values for the supported range
514// of [100, 999] (900 codes, 2700 bytes).
515const CODE_DIGITS: &str = "\
516100101102103104105106107108109110111112113114115116117118119\
517120121122123124125126127128129130131132133134135136137138139\
518140141142143144145146147148149150151152153154155156157158159\
519160161162163164165166167168169170171172173174175176177178179\
520180181182183184185186187188189190191192193194195196197198199\
521200201202203204205206207208209210211212213214215216217218219\
522220221222223224225226227228229230231232233234235236237238239\
523240241242243244245246247248249250251252253254255256257258259\
524260261262263264265266267268269270271272273274275276277278279\
525280281282283284285286287288289290291292293294295296297298299\
526300301302303304305306307308309310311312313314315316317318319\
527320321322323324325326327328329330331332333334335336337338339\
528340341342343344345346347348349350351352353354355356357358359\
529360361362363364365366367368369370371372373374375376377378379\
530380381382383384385386387388389390391392393394395396397398399\
531400401402403404405406407408409410411412413414415416417418419\
532420421422423424425426427428429430431432433434435436437438439\
533440441442443444445446447448449450451452453454455456457458459\
534460461462463464465466467468469470471472473474475476477478479\
535480481482483484485486487488489490491492493494495496497498499\
536500501502503504505506507508509510511512513514515516517518519\
537520521522523524525526527528529530531532533534535536537538539\
538540541542543544545546547548549550551552553554555556557558559\
539560561562563564565566567568569570571572573574575576577578579\
540580581582583584585586587588589590591592593594595596597598599\
541600601602603604605606607608609610611612613614615616617618619\
542620621622623624625626627628629630631632633634635636637638639\
543640641642643644645646647648649650651652653654655656657658659\
544660661662663664665666667668669670671672673674675676677678679\
545680681682683684685686687688689690691692693694695696697698699\
546700701702703704705706707708709710711712713714715716717718719\
547720721722723724725726727728729730731732733734735736737738739\
548740741742743744745746747748749750751752753754755756757758759\
549760761762763764765766767768769770771772773774775776777778779\
550780781782783784785786787788789790791792793794795796797798799\
551800801802803804805806807808809810811812813814815816817818819\
552820821822823824825826827828829830831832833834835836837838839\
553840841842843844845846847848849850851852853854855856857858859\
554860861862863864865866867868869870871872873874875876877878879\
555880881882883884885886887888889890891892893894895896897898899\
556900901902903904905906907908909910911912913914915916917918919\
557920921922923924925926927928929930931932933934935936937938939\
558940941942943944945946947948949950951952953954955956957958959\
559960961962963964965966967968969970971972973974975976977978979\
560980981982983984985986987988989990991992993994995996997998999";