]>
Commit | Line | Data |
---|---|---|
1b1a35ee | 1 | //! Numeric traits and functions for the built-in numeric types. |
0531ce1d | 2 | |
1b1a35ee | 3 | #![stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 4 | |
cdc7bbd5 | 5 | use crate::ascii; |
1b1a35ee XL |
6 | use crate::intrinsics; |
7 | use crate::mem; | |
04454e1e | 8 | use crate::ops::{Add, Mul, Sub}; |
1b1a35ee | 9 | use crate::str::FromStr; |
041b39d2 | 10 | |
1b1a35ee XL |
11 | // Used because the `?` operator is not allowed in a const context. |
12 | macro_rules! try_opt { | |
13 | ($e:expr) => { | |
14 | match $e { | |
15 | Some(x) => x, | |
16 | None => return None, | |
041b39d2 | 17 | } |
1b1a35ee XL |
18 | }; |
19 | } | |
041b39d2 | 20 | |
1b1a35ee XL |
21 | #[allow_internal_unstable(const_likely)] |
22 | macro_rules! unlikely { | |
23 | ($e: expr) => { | |
24 | intrinsics::unlikely($e) | |
25 | }; | |
26 | } | |
c34b1796 | 27 | |
1b1a35ee | 28 | // All these modules are technically private and only exposed for coretests: |
136023e0 | 29 | #[cfg(not(no_fp_fmt_parse))] |
1b1a35ee | 30 | pub mod bignum; |
136023e0 | 31 | #[cfg(not(no_fp_fmt_parse))] |
1b1a35ee | 32 | pub mod dec2flt; |
136023e0 | 33 | #[cfg(not(no_fp_fmt_parse))] |
1b1a35ee | 34 | pub mod diy_float; |
136023e0 | 35 | #[cfg(not(no_fp_fmt_parse))] |
1b1a35ee | 36 | pub mod flt2dec; |
136023e0 | 37 | pub mod fmt; |
0531ce1d | 38 | |
1b1a35ee XL |
39 | #[macro_use] |
40 | mod int_macros; // import int_impl! | |
41 | #[macro_use] | |
42 | mod uint_macros; // import uint_impl! | |
0531ce1d | 43 | |
1b1a35ee | 44 | mod error; |
136023e0 | 45 | mod int_log10; |
1b1a35ee | 46 | mod nonzero; |
94222f64 XL |
47 | #[unstable(feature = "saturating_int_impl", issue = "87920")] |
48 | mod saturating; | |
1b1a35ee | 49 | mod wrapping; |
83c7162d | 50 | |
94222f64 XL |
51 | #[unstable(feature = "saturating_int_impl", issue = "87920")] |
52 | pub use saturating::Saturating; | |
1b1a35ee XL |
53 | #[stable(feature = "rust1", since = "1.0.0")] |
54 | pub use wrapping::Wrapping; | |
94b46f34 | 55 | |
1b1a35ee | 56 | #[stable(feature = "rust1", since = "1.0.0")] |
136023e0 | 57 | #[cfg(not(no_fp_fmt_parse))] |
1b1a35ee | 58 | pub use dec2flt::ParseFloatError; |
94b46f34 | 59 | |
1b1a35ee XL |
60 | #[stable(feature = "rust1", since = "1.0.0")] |
61 | pub use error::ParseIntError; | |
94b46f34 | 62 | |
1b1a35ee XL |
63 | #[stable(feature = "nonzero", since = "1.28.0")] |
64 | pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; | |
94b46f34 | 65 | |
1b1a35ee XL |
66 | #[stable(feature = "signed_nonzero", since = "1.34.0")] |
67 | pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; | |
b7449926 | 68 | |
1b1a35ee XL |
69 | #[stable(feature = "try_from", since = "1.34.0")] |
70 | pub use error::TryFromIntError; | |
b7449926 | 71 | |
136023e0 | 72 | #[stable(feature = "int_error_matching", since = "1.55.0")] |
1b1a35ee | 73 | pub use error::IntErrorKind; |
b7449926 | 74 | |
1b1a35ee XL |
75 | macro_rules! usize_isize_to_xe_bytes_doc { |
76 | () => { | |
77 | " | |
b7449926 | 78 | |
1b1a35ee XL |
79 | **Note**: This function returns an array of length 2, 4 or 8 bytes |
80 | depending on the target pointer size. | |
b7449926 | 81 | |
48663c56 | 82 | " |
1b1a35ee XL |
83 | }; |
84 | } | |
b7449926 | 85 | |
1b1a35ee XL |
86 | macro_rules! usize_isize_from_xe_bytes_doc { |
87 | () => { | |
88 | " | |
b7449926 | 89 | |
1b1a35ee XL |
90 | **Note**: This function takes an array of length 2, 4 or 8 bytes |
91 | depending on the target pointer size. | |
b7449926 | 92 | |
48663c56 | 93 | " |
1b1a35ee | 94 | }; |
a1dfa0c6 | 95 | } |
b7449926 | 96 | |
94222f64 | 97 | macro_rules! widening_impl { |
3c0e092e | 98 | ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => { |
94222f64 XL |
99 | /// Calculates the complete product `self * rhs` without the possibility to overflow. |
100 | /// | |
101 | /// This returns the low-order (wrapping) bits and the high-order (overflow) bits | |
102 | /// of the result as two separate values, in that order. | |
103 | /// | |
104 | /// # Examples | |
105 | /// | |
106 | /// Basic usage: | |
107 | /// | |
108 | /// Please note that this example is shared between integer types. | |
109 | /// Which explains why `u32` is used here. | |
110 | /// | |
111 | /// ``` | |
112 | /// #![feature(bigint_helper_methods)] | |
113 | /// assert_eq!(5u32.widening_mul(2), (10, 0)); | |
114 | /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2)); | |
115 | /// ``` | |
116 | #[unstable(feature = "bigint_helper_methods", issue = "85532")] | |
117 | #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")] | |
118 | #[must_use = "this returns the result of the operation, \ | |
119 | without modifying the original"] | |
120 | #[inline] | |
121 | pub const fn widening_mul(self, rhs: Self) -> (Self, Self) { | |
122 | // note: longer-term this should be done via an intrinsic, | |
123 | // but for now we can deal without an impl for u128/i128 | |
124 | // SAFETY: overflow will be contained within the wider types | |
125 | let wide = unsafe { (self as $WideT).unchecked_mul(rhs as $WideT) }; | |
126 | (wide as $SelfT, (wide >> $BITS) as $SelfT) | |
127 | } | |
128 | ||
129 | /// Calculates the "full multiplication" `self * rhs + carry` | |
130 | /// without the possibility to overflow. | |
131 | /// | |
132 | /// This returns the low-order (wrapping) bits and the high-order (overflow) bits | |
133 | /// of the result as two separate values, in that order. | |
134 | /// | |
135 | /// Performs "long multiplication" which takes in an extra amount to add, and may return an | |
136 | /// additional amount of overflow. This allows for chaining together multiple | |
137 | /// multiplications to create "big integers" which represent larger values. | |
138 | /// | |
139 | /// # Examples | |
140 | /// | |
141 | /// Basic usage: | |
142 | /// | |
143 | /// Please note that this example is shared between integer types. | |
144 | /// Which explains why `u32` is used here. | |
145 | /// | |
146 | /// ``` | |
147 | /// #![feature(bigint_helper_methods)] | |
148 | /// assert_eq!(5u32.carrying_mul(2, 0), (10, 0)); | |
149 | /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0)); | |
150 | /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2)); | |
151 | /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2)); | |
3c0e092e XL |
152 | #[doc = concat!("assert_eq!(", |
153 | stringify!($SelfT), "::MAX.carrying_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ", | |
154 | "(0, ", stringify!($SelfT), "::MAX));" | |
155 | )] | |
156 | /// ``` | |
157 | /// | |
158 | /// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul), | |
159 | /// except that it gives the value of the overflow instead of just whether one happened: | |
160 | /// | |
161 | /// ``` | |
162 | /// #![feature(bigint_helper_methods)] | |
163 | /// let r = u8::carrying_mul(7, 13, 0); | |
164 | /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13)); | |
165 | /// let r = u8::carrying_mul(13, 42, 0); | |
166 | /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42)); | |
167 | /// ``` | |
168 | /// | |
169 | /// The value of the first field in the returned tuple matches what you'd get | |
170 | /// by combining the [`wrapping_mul`](Self::wrapping_mul) and | |
171 | /// [`wrapping_add`](Self::wrapping_add) methods: | |
172 | /// | |
173 | /// ``` | |
174 | /// #![feature(bigint_helper_methods)] | |
175 | /// assert_eq!( | |
176 | /// 789_u16.carrying_mul(456, 123).0, | |
177 | /// 789_u16.wrapping_mul(456).wrapping_add(123), | |
178 | /// ); | |
94222f64 XL |
179 | /// ``` |
180 | #[unstable(feature = "bigint_helper_methods", issue = "85532")] | |
181 | #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] | |
182 | #[must_use = "this returns the result of the operation, \ | |
183 | without modifying the original"] | |
184 | #[inline] | |
185 | pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) { | |
186 | // note: longer-term this should be done via an intrinsic, | |
187 | // but for now we can deal without an impl for u128/i128 | |
188 | // SAFETY: overflow will be contained within the wider types | |
189 | let wide = unsafe { | |
190 | (self as $WideT).unchecked_mul(rhs as $WideT).unchecked_add(carry as $WideT) | |
191 | }; | |
192 | (wide as $SelfT, (wide >> $BITS) as $SelfT) | |
193 | } | |
194 | }; | |
195 | } | |
196 | ||
1b1a35ee | 197 | impl i8 { |
94222f64 | 198 | int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48", |
1b1a35ee | 199 | "[0x12]", "[0x12]", "", "" } |
a1dfa0c6 | 200 | } |
a1dfa0c6 | 201 | |
1b1a35ee | 202 | impl i16 { |
94222f64 | 203 | int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412", |
1b1a35ee | 204 | "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } |
a1dfa0c6 | 205 | } |
74b04a01 | 206 | |
1b1a35ee | 207 | impl i32 { |
94222f64 | 208 | int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", |
1b1a35ee XL |
209 | "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", |
210 | "[0x12, 0x34, 0x56, 0x78]", "", "" } | |
211 | } | |
74b04a01 | 212 | |
1b1a35ee | 213 | impl i64 { |
94222f64 | 214 | int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12, |
1b1a35ee XL |
215 | "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", |
216 | "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", | |
217 | "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" } | |
218 | } | |
74b04a01 | 219 | |
1b1a35ee | 220 | impl i128 { |
94222f64 | 221 | int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728, |
5869c6ff | 222 | 170141183460469231731687303715884105727, 16, |
1b1a35ee XL |
223 | "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", |
224 | "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", | |
225 | "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ | |
226 | 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", | |
227 | "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ | |
228 | 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" } | |
229 | } | |
74b04a01 | 230 | |
1b1a35ee | 231 | #[cfg(target_pointer_width = "16")] |
1b1a35ee | 232 | impl isize { |
94222f64 | 233 | int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", |
1b1a35ee XL |
234 | "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", |
235 | usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } | |
236 | } | |
74b04a01 | 237 | |
1b1a35ee | 238 | #[cfg(target_pointer_width = "32")] |
1b1a35ee | 239 | impl isize { |
94222f64 | 240 | int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301", |
1b1a35ee XL |
241 | "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", |
242 | "[0x12, 0x34, 0x56, 0x78]", | |
243 | usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } | |
244 | } | |
74b04a01 | 245 | |
1b1a35ee | 246 | #[cfg(target_pointer_width = "64")] |
1b1a35ee | 247 | impl isize { |
94222f64 | 248 | int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807, |
1b1a35ee | 249 | 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", |
3c0e092e XL |
250 | "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", |
251 | "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", | |
252 | usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } | |
1a4d82fc JJ |
253 | } |
254 | ||
6a06907d XL |
255 | /// If 6th bit set ascii is upper case. |
256 | const ASCII_CASE_MASK: u8 = 0b0010_0000; | |
257 | ||
92a42be0 | 258 | impl u8 { |
5099ac24 | 259 | uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", |
60c5eb7d | 260 | "[0x12]", "", "" } |
3c0e092e | 261 | widening_impl! { u8, u16, 8, unsigned } |
abe05a73 XL |
262 | |
263 | /// Checks if the value is within the ASCII range. | |
264 | /// | |
265 | /// # Examples | |
266 | /// | |
267 | /// ``` | |
268 | /// let ascii = 97u8; | |
269 | /// let non_ascii = 150u8; | |
270 | /// | |
271 | /// assert!(ascii.is_ascii()); | |
272 | /// assert!(!non_ascii.is_ascii()); | |
273 | /// ``` | |
c295e0f8 | 274 | #[must_use] |
ff7c6d11 | 275 | #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] |
5e7ed085 | 276 | #[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")] |
abe05a73 | 277 | #[inline] |
74b04a01 | 278 | pub const fn is_ascii(&self) -> bool { |
abe05a73 XL |
279 | *self & 128 == 0 |
280 | } | |
281 | ||
282 | /// Makes a copy of the value in its ASCII upper case equivalent. | |
283 | /// | |
284 | /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', | |
285 | /// but non-ASCII letters are unchanged. | |
286 | /// | |
287 | /// To uppercase the value in-place, use [`make_ascii_uppercase`]. | |
288 | /// | |
289 | /// # Examples | |
290 | /// | |
291 | /// ``` | |
292 | /// let lowercase_a = 97u8; | |
293 | /// | |
294 | /// assert_eq!(65, lowercase_a.to_ascii_uppercase()); | |
295 | /// ``` | |
296 | /// | |
6a06907d | 297 | /// [`make_ascii_uppercase`]: Self::make_ascii_uppercase |
c295e0f8 | 298 | #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"] |
ff7c6d11 | 299 | #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] |
6a06907d | 300 | #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] |
abe05a73 | 301 | #[inline] |
6a06907d | 302 | pub const fn to_ascii_uppercase(&self) -> u8 { |
04454e1e FG |
303 | // Toggle the fifth bit if this is a lowercase letter |
304 | *self ^ ((self.is_ascii_lowercase() as u8) * ASCII_CASE_MASK) | |
abe05a73 XL |
305 | } |
306 | ||
307 | /// Makes a copy of the value in its ASCII lower case equivalent. | |
308 | /// | |
309 | /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', | |
310 | /// but non-ASCII letters are unchanged. | |
311 | /// | |
312 | /// To lowercase the value in-place, use [`make_ascii_lowercase`]. | |
313 | /// | |
314 | /// # Examples | |
315 | /// | |
316 | /// ``` | |
317 | /// let uppercase_a = 65u8; | |
318 | /// | |
319 | /// assert_eq!(97, uppercase_a.to_ascii_lowercase()); | |
320 | /// ``` | |
321 | /// | |
6a06907d | 322 | /// [`make_ascii_lowercase`]: Self::make_ascii_lowercase |
c295e0f8 | 323 | #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"] |
ff7c6d11 | 324 | #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] |
6a06907d | 325 | #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] |
abe05a73 | 326 | #[inline] |
6a06907d | 327 | pub const fn to_ascii_lowercase(&self) -> u8 { |
ba9703b0 | 328 | // Set the fifth bit if this is an uppercase letter |
6a06907d XL |
329 | *self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK) |
330 | } | |
331 | ||
332 | /// Assumes self is ascii | |
333 | #[inline] | |
334 | pub(crate) const fn ascii_change_case_unchecked(&self) -> u8 { | |
335 | *self ^ ASCII_CASE_MASK | |
abe05a73 XL |
336 | } |
337 | ||
338 | /// Checks that two values are an ASCII case-insensitive match. | |
339 | /// | |
340 | /// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`. | |
341 | /// | |
342 | /// # Examples | |
343 | /// | |
344 | /// ``` | |
345 | /// let lowercase_a = 97u8; | |
346 | /// let uppercase_a = 65u8; | |
347 | /// | |
348 | /// assert!(lowercase_a.eq_ignore_ascii_case(&uppercase_a)); | |
349 | /// ``` | |
ff7c6d11 | 350 | #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] |
6a06907d | 351 | #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")] |
abe05a73 | 352 | #[inline] |
6a06907d | 353 | pub const fn eq_ignore_ascii_case(&self, other: &u8) -> bool { |
abe05a73 XL |
354 | self.to_ascii_lowercase() == other.to_ascii_lowercase() |
355 | } | |
356 | ||
357 | /// Converts this value to its ASCII upper case equivalent in-place. | |
358 | /// | |
359 | /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', | |
360 | /// but non-ASCII letters are unchanged. | |
361 | /// | |
362 | /// To return a new uppercased value without modifying the existing one, use | |
363 | /// [`to_ascii_uppercase`]. | |
364 | /// | |
365 | /// # Examples | |
366 | /// | |
367 | /// ``` | |
368 | /// let mut byte = b'a'; | |
369 | /// | |
370 | /// byte.make_ascii_uppercase(); | |
371 | /// | |
372 | /// assert_eq!(b'A', byte); | |
373 | /// ``` | |
374 | /// | |
6a06907d | 375 | /// [`to_ascii_uppercase`]: Self::to_ascii_uppercase |
ff7c6d11 | 376 | #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] |
abe05a73 XL |
377 | #[inline] |
378 | pub fn make_ascii_uppercase(&mut self) { | |
379 | *self = self.to_ascii_uppercase(); | |
380 | } | |
381 | ||
382 | /// Converts this value to its ASCII lower case equivalent in-place. | |
383 | /// | |
384 | /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', | |
385 | /// but non-ASCII letters are unchanged. | |
386 | /// | |
387 | /// To return a new lowercased value without modifying the existing one, use | |
388 | /// [`to_ascii_lowercase`]. | |
389 | /// | |
390 | /// # Examples | |
391 | /// | |
392 | /// ``` | |
393 | /// let mut byte = b'A'; | |
394 | /// | |
395 | /// byte.make_ascii_lowercase(); | |
396 | /// | |
397 | /// assert_eq!(b'a', byte); | |
398 | /// ``` | |
399 | /// | |
6a06907d | 400 | /// [`to_ascii_lowercase`]: Self::to_ascii_lowercase |
ff7c6d11 | 401 | #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] |
abe05a73 XL |
402 | #[inline] |
403 | pub fn make_ascii_lowercase(&mut self) { | |
404 | *self = self.to_ascii_lowercase(); | |
405 | } | |
406 | ||
407 | /// Checks if the value is an ASCII alphabetic character: | |
408 | /// | |
dc9dc135 XL |
409 | /// - U+0041 'A' ..= U+005A 'Z', or |
410 | /// - U+0061 'a' ..= U+007A 'z'. | |
abe05a73 XL |
411 | /// |
412 | /// # Examples | |
413 | /// | |
414 | /// ``` | |
abe05a73 XL |
415 | /// let uppercase_a = b'A'; |
416 | /// let uppercase_g = b'G'; | |
417 | /// let a = b'a'; | |
418 | /// let g = b'g'; | |
419 | /// let zero = b'0'; | |
420 | /// let percent = b'%'; | |
421 | /// let space = b' '; | |
422 | /// let lf = b'\n'; | |
3c0e092e | 423 | /// let esc = b'\x1b'; |
abe05a73 XL |
424 | /// |
425 | /// assert!(uppercase_a.is_ascii_alphabetic()); | |
426 | /// assert!(uppercase_g.is_ascii_alphabetic()); | |
427 | /// assert!(a.is_ascii_alphabetic()); | |
428 | /// assert!(g.is_ascii_alphabetic()); | |
429 | /// assert!(!zero.is_ascii_alphabetic()); | |
430 | /// assert!(!percent.is_ascii_alphabetic()); | |
431 | /// assert!(!space.is_ascii_alphabetic()); | |
432 | /// assert!(!lf.is_ascii_alphabetic()); | |
433 | /// assert!(!esc.is_ascii_alphabetic()); | |
434 | /// ``` | |
c295e0f8 | 435 | #[must_use] |
ff7c6d11 | 436 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 437 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 438 | #[inline] |
74b04a01 | 439 | pub const fn is_ascii_alphabetic(&self) -> bool { |
dfeec247 | 440 | matches!(*self, b'A'..=b'Z' | b'a'..=b'z') |
abe05a73 XL |
441 | } |
442 | ||
443 | /// Checks if the value is an ASCII uppercase character: | |
dc9dc135 | 444 | /// U+0041 'A' ..= U+005A 'Z'. |
abe05a73 XL |
445 | /// |
446 | /// # Examples | |
447 | /// | |
448 | /// ``` | |
abe05a73 XL |
449 | /// let uppercase_a = b'A'; |
450 | /// let uppercase_g = b'G'; | |
451 | /// let a = b'a'; | |
452 | /// let g = b'g'; | |
453 | /// let zero = b'0'; | |
454 | /// let percent = b'%'; | |
455 | /// let space = b' '; | |
456 | /// let lf = b'\n'; | |
3c0e092e | 457 | /// let esc = b'\x1b'; |
abe05a73 XL |
458 | /// |
459 | /// assert!(uppercase_a.is_ascii_uppercase()); | |
460 | /// assert!(uppercase_g.is_ascii_uppercase()); | |
461 | /// assert!(!a.is_ascii_uppercase()); | |
462 | /// assert!(!g.is_ascii_uppercase()); | |
463 | /// assert!(!zero.is_ascii_uppercase()); | |
464 | /// assert!(!percent.is_ascii_uppercase()); | |
465 | /// assert!(!space.is_ascii_uppercase()); | |
466 | /// assert!(!lf.is_ascii_uppercase()); | |
467 | /// assert!(!esc.is_ascii_uppercase()); | |
468 | /// ``` | |
c295e0f8 | 469 | #[must_use] |
ff7c6d11 | 470 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 471 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 472 | #[inline] |
74b04a01 | 473 | pub const fn is_ascii_uppercase(&self) -> bool { |
dfeec247 | 474 | matches!(*self, b'A'..=b'Z') |
abe05a73 XL |
475 | } |
476 | ||
477 | /// Checks if the value is an ASCII lowercase character: | |
dc9dc135 | 478 | /// U+0061 'a' ..= U+007A 'z'. |
abe05a73 XL |
479 | /// |
480 | /// # Examples | |
481 | /// | |
482 | /// ``` | |
abe05a73 XL |
483 | /// let uppercase_a = b'A'; |
484 | /// let uppercase_g = b'G'; | |
485 | /// let a = b'a'; | |
486 | /// let g = b'g'; | |
487 | /// let zero = b'0'; | |
488 | /// let percent = b'%'; | |
489 | /// let space = b' '; | |
490 | /// let lf = b'\n'; | |
3c0e092e | 491 | /// let esc = b'\x1b'; |
abe05a73 XL |
492 | /// |
493 | /// assert!(!uppercase_a.is_ascii_lowercase()); | |
494 | /// assert!(!uppercase_g.is_ascii_lowercase()); | |
495 | /// assert!(a.is_ascii_lowercase()); | |
496 | /// assert!(g.is_ascii_lowercase()); | |
497 | /// assert!(!zero.is_ascii_lowercase()); | |
498 | /// assert!(!percent.is_ascii_lowercase()); | |
499 | /// assert!(!space.is_ascii_lowercase()); | |
500 | /// assert!(!lf.is_ascii_lowercase()); | |
501 | /// assert!(!esc.is_ascii_lowercase()); | |
502 | /// ``` | |
c295e0f8 | 503 | #[must_use] |
ff7c6d11 | 504 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 505 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 506 | #[inline] |
74b04a01 | 507 | pub const fn is_ascii_lowercase(&self) -> bool { |
dfeec247 | 508 | matches!(*self, b'a'..=b'z') |
abe05a73 XL |
509 | } |
510 | ||
511 | /// Checks if the value is an ASCII alphanumeric character: | |
512 | /// | |
dc9dc135 XL |
513 | /// - U+0041 'A' ..= U+005A 'Z', or |
514 | /// - U+0061 'a' ..= U+007A 'z', or | |
515 | /// - U+0030 '0' ..= U+0039 '9'. | |
abe05a73 XL |
516 | /// |
517 | /// # Examples | |
518 | /// | |
519 | /// ``` | |
abe05a73 XL |
520 | /// let uppercase_a = b'A'; |
521 | /// let uppercase_g = b'G'; | |
522 | /// let a = b'a'; | |
523 | /// let g = b'g'; | |
524 | /// let zero = b'0'; | |
525 | /// let percent = b'%'; | |
526 | /// let space = b' '; | |
527 | /// let lf = b'\n'; | |
3c0e092e | 528 | /// let esc = b'\x1b'; |
abe05a73 XL |
529 | /// |
530 | /// assert!(uppercase_a.is_ascii_alphanumeric()); | |
531 | /// assert!(uppercase_g.is_ascii_alphanumeric()); | |
532 | /// assert!(a.is_ascii_alphanumeric()); | |
533 | /// assert!(g.is_ascii_alphanumeric()); | |
534 | /// assert!(zero.is_ascii_alphanumeric()); | |
535 | /// assert!(!percent.is_ascii_alphanumeric()); | |
536 | /// assert!(!space.is_ascii_alphanumeric()); | |
537 | /// assert!(!lf.is_ascii_alphanumeric()); | |
538 | /// assert!(!esc.is_ascii_alphanumeric()); | |
539 | /// ``` | |
c295e0f8 | 540 | #[must_use] |
ff7c6d11 | 541 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 542 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 543 | #[inline] |
74b04a01 | 544 | pub const fn is_ascii_alphanumeric(&self) -> bool { |
dfeec247 | 545 | matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z') |
abe05a73 XL |
546 | } |
547 | ||
548 | /// Checks if the value is an ASCII decimal digit: | |
dc9dc135 | 549 | /// U+0030 '0' ..= U+0039 '9'. |
abe05a73 XL |
550 | /// |
551 | /// # Examples | |
552 | /// | |
553 | /// ``` | |
abe05a73 XL |
554 | /// let uppercase_a = b'A'; |
555 | /// let uppercase_g = b'G'; | |
556 | /// let a = b'a'; | |
557 | /// let g = b'g'; | |
558 | /// let zero = b'0'; | |
559 | /// let percent = b'%'; | |
560 | /// let space = b' '; | |
561 | /// let lf = b'\n'; | |
3c0e092e | 562 | /// let esc = b'\x1b'; |
abe05a73 XL |
563 | /// |
564 | /// assert!(!uppercase_a.is_ascii_digit()); | |
565 | /// assert!(!uppercase_g.is_ascii_digit()); | |
566 | /// assert!(!a.is_ascii_digit()); | |
567 | /// assert!(!g.is_ascii_digit()); | |
568 | /// assert!(zero.is_ascii_digit()); | |
569 | /// assert!(!percent.is_ascii_digit()); | |
570 | /// assert!(!space.is_ascii_digit()); | |
571 | /// assert!(!lf.is_ascii_digit()); | |
572 | /// assert!(!esc.is_ascii_digit()); | |
573 | /// ``` | |
c295e0f8 | 574 | #[must_use] |
ff7c6d11 | 575 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 576 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 577 | #[inline] |
74b04a01 | 578 | pub const fn is_ascii_digit(&self) -> bool { |
dfeec247 | 579 | matches!(*self, b'0'..=b'9') |
abe05a73 XL |
580 | } |
581 | ||
582 | /// Checks if the value is an ASCII hexadecimal digit: | |
583 | /// | |
dc9dc135 XL |
584 | /// - U+0030 '0' ..= U+0039 '9', or |
585 | /// - U+0041 'A' ..= U+0046 'F', or | |
586 | /// - U+0061 'a' ..= U+0066 'f'. | |
abe05a73 XL |
587 | /// |
588 | /// # Examples | |
589 | /// | |
590 | /// ``` | |
abe05a73 XL |
591 | /// let uppercase_a = b'A'; |
592 | /// let uppercase_g = b'G'; | |
593 | /// let a = b'a'; | |
594 | /// let g = b'g'; | |
595 | /// let zero = b'0'; | |
596 | /// let percent = b'%'; | |
597 | /// let space = b' '; | |
598 | /// let lf = b'\n'; | |
3c0e092e | 599 | /// let esc = b'\x1b'; |
abe05a73 XL |
600 | /// |
601 | /// assert!(uppercase_a.is_ascii_hexdigit()); | |
602 | /// assert!(!uppercase_g.is_ascii_hexdigit()); | |
603 | /// assert!(a.is_ascii_hexdigit()); | |
604 | /// assert!(!g.is_ascii_hexdigit()); | |
605 | /// assert!(zero.is_ascii_hexdigit()); | |
606 | /// assert!(!percent.is_ascii_hexdigit()); | |
607 | /// assert!(!space.is_ascii_hexdigit()); | |
608 | /// assert!(!lf.is_ascii_hexdigit()); | |
609 | /// assert!(!esc.is_ascii_hexdigit()); | |
610 | /// ``` | |
c295e0f8 | 611 | #[must_use] |
ff7c6d11 | 612 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 613 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 614 | #[inline] |
74b04a01 | 615 | pub const fn is_ascii_hexdigit(&self) -> bool { |
dfeec247 | 616 | matches!(*self, b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f') |
abe05a73 XL |
617 | } |
618 | ||
619 | /// Checks if the value is an ASCII punctuation character: | |
620 | /// | |
dc9dc135 XL |
621 | /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or |
622 | /// - U+003A ..= U+0040 `: ; < = > ? @`, or | |
623 | /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or | |
624 | /// - U+007B ..= U+007E `{ | } ~` | |
abe05a73 XL |
625 | /// |
626 | /// # Examples | |
627 | /// | |
628 | /// ``` | |
abe05a73 XL |
629 | /// let uppercase_a = b'A'; |
630 | /// let uppercase_g = b'G'; | |
631 | /// let a = b'a'; | |
632 | /// let g = b'g'; | |
633 | /// let zero = b'0'; | |
634 | /// let percent = b'%'; | |
635 | /// let space = b' '; | |
636 | /// let lf = b'\n'; | |
3c0e092e | 637 | /// let esc = b'\x1b'; |
abe05a73 XL |
638 | /// |
639 | /// assert!(!uppercase_a.is_ascii_punctuation()); | |
640 | /// assert!(!uppercase_g.is_ascii_punctuation()); | |
641 | /// assert!(!a.is_ascii_punctuation()); | |
642 | /// assert!(!g.is_ascii_punctuation()); | |
643 | /// assert!(!zero.is_ascii_punctuation()); | |
644 | /// assert!(percent.is_ascii_punctuation()); | |
645 | /// assert!(!space.is_ascii_punctuation()); | |
646 | /// assert!(!lf.is_ascii_punctuation()); | |
647 | /// assert!(!esc.is_ascii_punctuation()); | |
648 | /// ``` | |
c295e0f8 | 649 | #[must_use] |
ff7c6d11 | 650 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 651 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 652 | #[inline] |
74b04a01 | 653 | pub const fn is_ascii_punctuation(&self) -> bool { |
dfeec247 | 654 | matches!(*self, b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~') |
abe05a73 XL |
655 | } |
656 | ||
657 | /// Checks if the value is an ASCII graphic character: | |
dc9dc135 | 658 | /// U+0021 '!' ..= U+007E '~'. |
abe05a73 XL |
659 | /// |
660 | /// # Examples | |
661 | /// | |
662 | /// ``` | |
abe05a73 XL |
663 | /// let uppercase_a = b'A'; |
664 | /// let uppercase_g = b'G'; | |
665 | /// let a = b'a'; | |
666 | /// let g = b'g'; | |
667 | /// let zero = b'0'; | |
668 | /// let percent = b'%'; | |
669 | /// let space = b' '; | |
670 | /// let lf = b'\n'; | |
3c0e092e | 671 | /// let esc = b'\x1b'; |
abe05a73 XL |
672 | /// |
673 | /// assert!(uppercase_a.is_ascii_graphic()); | |
674 | /// assert!(uppercase_g.is_ascii_graphic()); | |
675 | /// assert!(a.is_ascii_graphic()); | |
676 | /// assert!(g.is_ascii_graphic()); | |
677 | /// assert!(zero.is_ascii_graphic()); | |
678 | /// assert!(percent.is_ascii_graphic()); | |
679 | /// assert!(!space.is_ascii_graphic()); | |
680 | /// assert!(!lf.is_ascii_graphic()); | |
681 | /// assert!(!esc.is_ascii_graphic()); | |
682 | /// ``` | |
c295e0f8 | 683 | #[must_use] |
ff7c6d11 | 684 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 685 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 686 | #[inline] |
74b04a01 | 687 | pub const fn is_ascii_graphic(&self) -> bool { |
dfeec247 | 688 | matches!(*self, b'!'..=b'~') |
abe05a73 XL |
689 | } |
690 | ||
691 | /// Checks if the value is an ASCII whitespace character: | |
692 | /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED, | |
693 | /// U+000C FORM FEED, or U+000D CARRIAGE RETURN. | |
694 | /// | |
695 | /// Rust uses the WhatWG Infra Standard's [definition of ASCII | |
696 | /// whitespace][infra-aw]. There are several other definitions in | |
697 | /// wide use. For instance, [the POSIX locale][pct] includes | |
698 | /// U+000B VERTICAL TAB as well as all the above characters, | |
699 | /// but—from the very same specification—[the default rule for | |
700 | /// "field splitting" in the Bourne shell][bfs] considers *only* | |
701 | /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace. | |
702 | /// | |
703 | /// If you are writing a program that will process an existing | |
704 | /// file format, check what that format's definition of whitespace is | |
705 | /// before using this function. | |
706 | /// | |
707 | /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace | |
136023e0 XL |
708 | /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 |
709 | /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 | |
abe05a73 XL |
710 | /// |
711 | /// # Examples | |
712 | /// | |
713 | /// ``` | |
abe05a73 XL |
714 | /// let uppercase_a = b'A'; |
715 | /// let uppercase_g = b'G'; | |
716 | /// let a = b'a'; | |
717 | /// let g = b'g'; | |
718 | /// let zero = b'0'; | |
719 | /// let percent = b'%'; | |
720 | /// let space = b' '; | |
721 | /// let lf = b'\n'; | |
3c0e092e | 722 | /// let esc = b'\x1b'; |
abe05a73 XL |
723 | /// |
724 | /// assert!(!uppercase_a.is_ascii_whitespace()); | |
725 | /// assert!(!uppercase_g.is_ascii_whitespace()); | |
726 | /// assert!(!a.is_ascii_whitespace()); | |
727 | /// assert!(!g.is_ascii_whitespace()); | |
728 | /// assert!(!zero.is_ascii_whitespace()); | |
729 | /// assert!(!percent.is_ascii_whitespace()); | |
730 | /// assert!(space.is_ascii_whitespace()); | |
731 | /// assert!(lf.is_ascii_whitespace()); | |
732 | /// assert!(!esc.is_ascii_whitespace()); | |
733 | /// ``` | |
c295e0f8 | 734 | #[must_use] |
ff7c6d11 | 735 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 736 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 737 | #[inline] |
74b04a01 | 738 | pub const fn is_ascii_whitespace(&self) -> bool { |
dfeec247 | 739 | matches!(*self, b'\t' | b'\n' | b'\x0C' | b'\r' | b' ') |
abe05a73 XL |
740 | } |
741 | ||
742 | /// Checks if the value is an ASCII control character: | |
dc9dc135 | 743 | /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE. |
abe05a73 XL |
744 | /// Note that most ASCII whitespace characters are control |
745 | /// characters, but SPACE is not. | |
746 | /// | |
747 | /// # Examples | |
748 | /// | |
749 | /// ``` | |
abe05a73 XL |
750 | /// let uppercase_a = b'A'; |
751 | /// let uppercase_g = b'G'; | |
752 | /// let a = b'a'; | |
753 | /// let g = b'g'; | |
754 | /// let zero = b'0'; | |
755 | /// let percent = b'%'; | |
756 | /// let space = b' '; | |
757 | /// let lf = b'\n'; | |
3c0e092e | 758 | /// let esc = b'\x1b'; |
abe05a73 XL |
759 | /// |
760 | /// assert!(!uppercase_a.is_ascii_control()); | |
761 | /// assert!(!uppercase_g.is_ascii_control()); | |
762 | /// assert!(!a.is_ascii_control()); | |
763 | /// assert!(!g.is_ascii_control()); | |
764 | /// assert!(!zero.is_ascii_control()); | |
765 | /// assert!(!percent.is_ascii_control()); | |
766 | /// assert!(!space.is_ascii_control()); | |
767 | /// assert!(lf.is_ascii_control()); | |
768 | /// assert!(esc.is_ascii_control()); | |
769 | /// ``` | |
c295e0f8 | 770 | #[must_use] |
ff7c6d11 | 771 | #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")] |
3dfed10e | 772 | #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")] |
abe05a73 | 773 | #[inline] |
74b04a01 | 774 | pub const fn is_ascii_control(&self) -> bool { |
dfeec247 | 775 | matches!(*self, b'\0'..=b'\x1F' | b'\x7F') |
abe05a73 | 776 | } |
cdc7bbd5 XL |
777 | |
778 | /// Returns an iterator that produces an escaped version of a `u8`, | |
779 | /// treating it as an ASCII character. | |
780 | /// | |
781 | /// The behavior is identical to [`ascii::escape_default`]. | |
782 | /// | |
783 | /// # Examples | |
784 | /// | |
785 | /// ``` | |
cdc7bbd5 XL |
786 | /// |
787 | /// assert_eq!("0", b'0'.escape_ascii().to_string()); | |
788 | /// assert_eq!("\\t", b'\t'.escape_ascii().to_string()); | |
789 | /// assert_eq!("\\r", b'\r'.escape_ascii().to_string()); | |
790 | /// assert_eq!("\\n", b'\n'.escape_ascii().to_string()); | |
791 | /// assert_eq!("\\'", b'\''.escape_ascii().to_string()); | |
792 | /// assert_eq!("\\\"", b'"'.escape_ascii().to_string()); | |
793 | /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string()); | |
794 | /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string()); | |
795 | /// ``` | |
c295e0f8 XL |
796 | #[must_use = "this returns the escaped byte as an iterator, \ |
797 | without modifying the original"] | |
5099ac24 | 798 | #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] |
cdc7bbd5 | 799 | #[inline] |
5099ac24 FG |
800 | pub fn escape_ascii(self) -> ascii::EscapeDefault { |
801 | ascii::escape_default(self) | |
802 | } | |
803 | ||
5e7ed085 FG |
804 | #[inline] |
805 | pub(crate) const fn is_utf8_char_boundary(self) -> bool { | |
5099ac24 FG |
806 | // This is bit magic equivalent to: b < 128 || b >= 192 |
807 | (self as i8) >= -0x40 | |
cdc7bbd5 | 808 | } |
92a42be0 | 809 | } |
1a4d82fc | 810 | |
92a42be0 | 811 | impl u16 { |
5099ac24 | 812 | uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", |
60c5eb7d | 813 | "[0x34, 0x12]", "[0x12, 0x34]", "", "" } |
3c0e092e | 814 | widening_impl! { u16, u32, 16, unsigned } |
5e7ed085 FG |
815 | |
816 | /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`]. | |
817 | /// | |
818 | /// # Examples | |
819 | /// | |
820 | /// ``` | |
821 | /// #![feature(utf16_extra)] | |
822 | /// | |
823 | /// let low_non_surrogate = 0xA000u16; | |
824 | /// let low_surrogate = 0xD800u16; | |
825 | /// let high_surrogate = 0xDC00u16; | |
826 | /// let high_non_surrogate = 0xE000u16; | |
827 | /// | |
828 | /// assert!(!low_non_surrogate.is_utf16_surrogate()); | |
829 | /// assert!(low_surrogate.is_utf16_surrogate()); | |
830 | /// assert!(high_surrogate.is_utf16_surrogate()); | |
831 | /// assert!(!high_non_surrogate.is_utf16_surrogate()); | |
832 | /// ``` | |
833 | #[must_use] | |
834 | #[unstable(feature = "utf16_extra", issue = "94919")] | |
835 | #[rustc_const_unstable(feature = "utf16_extra_const", issue = "94919")] | |
836 | #[inline] | |
837 | pub const fn is_utf16_surrogate(self) -> bool { | |
838 | matches!(self, 0xD800..=0xDFFF) | |
839 | } | |
92a42be0 | 840 | } |
1a4d82fc | 841 | |
92a42be0 | 842 | impl u32 { |
5099ac24 | 843 | uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", |
60c5eb7d | 844 | "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } |
3c0e092e | 845 | widening_impl! { u32, u64, 32, unsigned } |
92a42be0 | 846 | } |
1a4d82fc | 847 | |
92a42be0 | 848 | impl u64 { |
5099ac24 | 849 | uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", |
60c5eb7d XL |
850 | "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", |
851 | "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", | |
852 | "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", | |
853 | "", ""} | |
3c0e092e | 854 | widening_impl! { u64, u128, 64, unsigned } |
92a42be0 | 855 | } |
c34b1796 | 856 | |
32a655c1 | 857 | impl u128 { |
5099ac24 | 858 | uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16, |
60c5eb7d XL |
859 | "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", |
860 | "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", | |
861 | "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ | |
862 | 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", | |
863 | "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \ | |
864 | 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", | |
865 | "", ""} | |
32a655c1 SL |
866 | } |
867 | ||
3157f602 | 868 | #[cfg(target_pointer_width = "16")] |
3157f602 | 869 | impl usize { |
5099ac24 | 870 | uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", |
60c5eb7d XL |
871 | "[0x34, 0x12]", "[0x12, 0x34]", |
872 | usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } | |
3c0e092e | 873 | widening_impl! { usize, u32, 16, unsigned } |
3157f602 | 874 | } |
c34b1796 | 875 | #[cfg(target_pointer_width = "32")] |
92a42be0 | 876 | impl usize { |
5099ac24 | 877 | uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", |
60c5eb7d XL |
878 | "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", |
879 | usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } | |
3c0e092e | 880 | widening_impl! { usize, u64, 32, unsigned } |
92a42be0 | 881 | } |
c34b1796 AL |
882 | |
883 | #[cfg(target_pointer_width = "64")] | |
92a42be0 | 884 | impl usize { |
5099ac24 | 885 | uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", |
60c5eb7d XL |
886 | "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", |
887 | "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", | |
3c0e092e | 888 | "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", |
60c5eb7d | 889 | usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } |
3c0e092e | 890 | widening_impl! { usize, u128, 64, unsigned } |
92a42be0 | 891 | } |
1a4d82fc | 892 | |
04454e1e FG |
893 | impl usize { |
894 | /// Returns an `usize` where every byte is equal to `x`. | |
895 | #[inline] | |
896 | pub(crate) const fn repeat_u8(x: u8) -> usize { | |
897 | usize::from_ne_bytes([x; mem::size_of::<usize>()]) | |
898 | } | |
899 | ||
900 | /// Returns an `usize` where every byte pair is equal to `x`. | |
901 | #[inline] | |
902 | pub(crate) const fn repeat_u16(x: u16) -> usize { | |
903 | let mut r = 0usize; | |
904 | let mut i = 0; | |
905 | while i < mem::size_of::<usize>() { | |
906 | // Use `wrapping_shl` to make it work on targets with 16-bit `usize` | |
907 | r = r.wrapping_shl(16) | (x as usize); | |
908 | i += 2; | |
909 | } | |
910 | r | |
911 | } | |
912 | } | |
913 | ||
7453a54e SL |
914 | /// A classification of floating point numbers. |
915 | /// | |
cc61c64b | 916 | /// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See |
7453a54e SL |
917 | /// their documentation for more. |
918 | /// | |
5bcae85e SL |
919 | /// # Examples |
920 | /// | |
921 | /// ``` | |
922 | /// use std::num::FpCategory; | |
5bcae85e SL |
923 | /// |
924 | /// let num = 12.4_f32; | |
925 | /// let inf = f32::INFINITY; | |
926 | /// let zero = 0f32; | |
927 | /// let sub: f32 = 1.1754942e-38; | |
928 | /// let nan = f32::NAN; | |
929 | /// | |
930 | /// assert_eq!(num.classify(), FpCategory::Normal); | |
931 | /// assert_eq!(inf.classify(), FpCategory::Infinite); | |
932 | /// assert_eq!(zero.classify(), FpCategory::Zero); | |
933 | /// assert_eq!(nan.classify(), FpCategory::Nan); | |
934 | /// assert_eq!(sub.classify(), FpCategory::Subnormal); | |
935 | /// ``` | |
9e0c209e | 936 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
c34b1796 | 937 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 938 | pub enum FpCategory { |
c295e0f8 XL |
939 | /// NaN (not a number): this value results from calculations like `(-1.0).sqrt()`. |
940 | /// | |
941 | /// See [the documentation for `f32`](f32) for more information on the unusual properties | |
942 | /// of NaN. | |
c34b1796 | 943 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 944 | Nan, |
c34b1796 | 945 | |
c295e0f8 XL |
946 | /// Positive or negative infinity, which often results from dividing a nonzero number |
947 | /// by zero. | |
c34b1796 | 948 | #[stable(feature = "rust1", since = "1.0.0")] |
c30ab7b3 | 949 | Infinite, |
c34b1796 | 950 | |
5bcae85e | 951 | /// Positive or negative zero. |
c295e0f8 XL |
952 | /// |
953 | /// See [the documentation for `f32`](f32) for more information on the signedness of zeroes. | |
c34b1796 | 954 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 955 | Zero, |
c34b1796 | 956 | |
c295e0f8 XL |
957 | /// “Subnormal” or “denormal” floating point representation (less precise, relative to |
958 | /// their magnitude, than [`Normal`]). | |
959 | /// | |
960 | /// Subnormal numbers are larger in magnitude than [`Zero`] but smaller in magnitude than all | |
961 | /// [`Normal`] numbers. | |
962 | /// | |
963 | /// [`Normal`]: Self::Normal | |
964 | /// [`Zero`]: Self::Zero | |
c34b1796 | 965 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 966 | Subnormal, |
c34b1796 | 967 | |
c295e0f8 XL |
968 | /// A regular floating point number, not any of the exceptional categories. |
969 | /// | |
970 | /// The smallest positive normal numbers are [`f32::MIN_POSITIVE`] and [`f64::MIN_POSITIVE`], | |
971 | /// and the largest positive normal numbers are [`f32::MAX`] and [`f64::MAX`]. (Unlike signed | |
972 | /// integers, floating point numbers are symmetric in their range, so negating any of these | |
973 | /// constants will produce their negative counterpart.) | |
c34b1796 | 974 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
975 | Normal, |
976 | } | |
977 | ||
1b1a35ee | 978 | #[doc(hidden)] |
04454e1e FG |
979 | trait FromStrRadixHelper: |
980 | PartialOrd + Copy + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self> | |
981 | { | |
982 | const MIN: Self; | |
1b1a35ee XL |
983 | fn from_u32(u: u32) -> Self; |
984 | fn checked_mul(&self, other: u32) -> Option<Self>; | |
985 | fn checked_sub(&self, other: u32) -> Option<Self>; | |
986 | fn checked_add(&self, other: u32) -> Option<Self>; | |
987 | } | |
988 | ||
1a4d82fc | 989 | macro_rules! from_str_radix_int_impl { |
62682a34 | 990 | ($($t:ty)*) => {$( |
85aaf69f | 991 | #[stable(feature = "rust1", since = "1.0.0")] |
62682a34 | 992 | impl FromStr for $t { |
85aaf69f | 993 | type Err = ParseIntError; |
62682a34 | 994 | fn from_str(src: &str) -> Result<Self, ParseIntError> { |
1a4d82fc JJ |
995 | from_str_radix(src, 10) |
996 | } | |
997 | } | |
9346a6ac AL |
998 | )*} |
999 | } | |
8bb4bdeb | 1000 | from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } |
1a4d82fc | 1001 | |
04454e1e | 1002 | macro_rules! impl_helper_for { |
62682a34 | 1003 | ($($t:ty)*) => ($(impl FromStrRadixHelper for $t { |
04454e1e | 1004 | const MIN: Self = Self::MIN; |
3b2f2976 | 1005 | #[inline] |
62682a34 | 1006 | fn from_u32(u: u32) -> Self { u as Self } |
3b2f2976 | 1007 | #[inline] |
9346a6ac | 1008 | fn checked_mul(&self, other: u32) -> Option<Self> { |
62682a34 | 1009 | Self::checked_mul(*self, other as Self) |
1a4d82fc | 1010 | } |
3b2f2976 | 1011 | #[inline] |
9346a6ac | 1012 | fn checked_sub(&self, other: u32) -> Option<Self> { |
62682a34 | 1013 | Self::checked_sub(*self, other as Self) |
9346a6ac | 1014 | } |
3b2f2976 | 1015 | #[inline] |
9346a6ac | 1016 | fn checked_add(&self, other: u32) -> Option<Self> { |
62682a34 | 1017 | Self::checked_add(*self, other as Self) |
9346a6ac AL |
1018 | } |
1019 | })*) | |
1020 | } | |
04454e1e FG |
1021 | impl_helper_for! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } |
1022 | ||
1023 | /// Determines if a string of text of that length of that radix could be guaranteed to be | |
1024 | /// stored in the given type T. | |
1025 | /// Note that if the radix is known to the compiler, it is just the check of digits.len that | |
1026 | /// is done at runtime. | |
1027 | #[doc(hidden)] | |
1028 | #[inline(always)] | |
1029 | #[unstable(issue = "none", feature = "std_internals")] | |
1030 | pub fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { | |
1031 | radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize | |
1032 | } | |
9346a6ac | 1033 | |
c30ab7b3 | 1034 | fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> { |
9346a6ac AL |
1035 | use self::IntErrorKind::*; |
1036 | use self::ParseIntError as PIE; | |
c1a9b12d | 1037 | |
60c5eb7d | 1038 | assert!( |
94222f64 | 1039 | (2..=36).contains(&radix), |
60c5eb7d XL |
1040 | "from_str_radix_int: must lie in the range `[2, 36]` - found {}", |
1041 | radix | |
1042 | ); | |
9346a6ac | 1043 | |
c1a9b12d SL |
1044 | if src.is_empty() { |
1045 | return Err(PIE { kind: Empty }); | |
1046 | } | |
1047 | ||
04454e1e | 1048 | let is_signed_ty = T::from_u32(0) > T::MIN; |
9346a6ac | 1049 | |
c1a9b12d SL |
1050 | // all valid digits are ascii, so we will just iterate over the utf8 bytes |
1051 | // and cast them to chars. .to_digit() will safely return None for anything | |
b039eaaf | 1052 | // other than a valid ascii digit for the given radix, including the first-byte |
c1a9b12d SL |
1053 | // of multi-byte sequences |
1054 | let src = src.as_bytes(); | |
1055 | ||
b039eaaf | 1056 | let (is_positive, digits) = match src[0] { |
29967ef6 XL |
1057 | b'+' | b'-' if src[1..].is_empty() => { |
1058 | return Err(PIE { kind: InvalidDigit }); | |
1059 | } | |
b039eaaf SL |
1060 | b'+' => (true, &src[1..]), |
1061 | b'-' if is_signed_ty => (false, &src[1..]), | |
c30ab7b3 | 1062 | _ => (true, src), |
b039eaaf SL |
1063 | }; |
1064 | ||
b039eaaf | 1065 | let mut result = T::from_u32(0); |
04454e1e FG |
1066 | |
1067 | if can_not_overflow::<T>(radix, is_signed_ty, digits) { | |
1068 | // If the len of the str is short compared to the range of the type | |
1069 | // we are parsing into, then we can be certain that an overflow will not occur. | |
1070 | // This bound is when `radix.pow(digits.len()) - 1 <= T::MAX` but the condition | |
1071 | // above is a faster (conservative) approximation of this. | |
1072 | // | |
1073 | // Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest: | |
1074 | // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow. | |
1075 | // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow. | |
1076 | macro_rules! run_unchecked_loop { | |
1077 | ($unchecked_additive_op:expr) => { | |
1078 | for &c in digits { | |
1079 | result = result * T::from_u32(radix); | |
1080 | let x = (c as char).to_digit(radix).ok_or(PIE { kind: InvalidDigit })?; | |
1081 | result = $unchecked_additive_op(result, T::from_u32(x)); | |
1082 | } | |
b039eaaf SL |
1083 | }; |
1084 | } | |
04454e1e FG |
1085 | if is_positive { |
1086 | run_unchecked_loop!(<T as core::ops::Add>::add) | |
1087 | } else { | |
1088 | run_unchecked_loop!(<T as core::ops::Sub>::sub) | |
1089 | }; | |
b039eaaf | 1090 | } else { |
04454e1e FG |
1091 | macro_rules! run_checked_loop { |
1092 | ($checked_additive_op:ident, $overflow_err:expr) => { | |
1093 | for &c in digits { | |
1094 | // When `radix` is passed in as a literal, rather than doing a slow `imul` | |
1095 | // the compiler can use shifts if `radix` can be expressed as a | |
1096 | // sum of powers of 2 (x*10 can be written as x*8 + x*2). | |
1097 | // When the compiler can't use these optimisations, | |
1098 | // the latency of the multiplication can be hidden by issuing it | |
1099 | // before the result is needed to improve performance on | |
1100 | // modern out-of-order CPU as multiplication here is slower | |
1101 | // than the other instructions, we can get the end result faster | |
1102 | // doing multiplication first and let the CPU spends other cycles | |
1103 | // doing other computation and get multiplication result later. | |
1104 | let mul = result.checked_mul(radix); | |
1105 | let x = (c as char).to_digit(radix).ok_or(PIE { kind: InvalidDigit })?; | |
1106 | result = mul.ok_or_else($overflow_err)?; | |
1107 | result = T::$checked_additive_op(&result, x).ok_or_else($overflow_err)?; | |
1108 | } | |
b039eaaf | 1109 | }; |
c1a9b12d | 1110 | } |
04454e1e FG |
1111 | if is_positive { |
1112 | run_checked_loop!(checked_add, || PIE { kind: PosOverflow }) | |
1113 | } else { | |
1114 | run_checked_loop!(checked_sub, || PIE { kind: NegOverflow }) | |
1115 | }; | |
1a4d82fc | 1116 | } |
b039eaaf | 1117 | Ok(result) |
1a4d82fc | 1118 | } |