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