core/num/mod.rs
1//! Numeric traits and functions for the built-in numeric types.
2
3#![stable(feature = "rust1", since = "1.0.0")]
4#![expect(clippy::manual_is_ascii_check, reason = "this module implements various is_ascii checks")]
5
6use crate::convert::{BoundedCastFromInt, CheckedCastFromInt};
7use crate::panic::const_panic;
8use crate::str::FromStr;
9use crate::ub_checks::assert_unsafe_precondition;
10use crate::{ascii, intrinsics, mem};
11
12// FIXME(const-hack): Used because the `?` operator is not allowed in a const context.
13macro_rules! try_opt {
14 ($e:expr) => {
15 match $e {
16 Some(x) => x,
17 None => return None,
18 }
19 };
20}
21
22// Use this when the generated code should differ between signed and unsigned types.
23macro_rules! sign_dependent_expr {
24 (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
25 $signed_case
26 };
27 (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
28 $unsigned_case
29 };
30}
31
32// These modules are public only for testing.
33#[doc(hidden)]
34#[unstable(
35 feature = "num_internals",
36 reason = "internal routines only exposed for testing",
37 issue = "none"
38)]
39pub mod imp;
40
41#[macro_use]
42mod int_macros; // import int_impl!
43#[macro_use]
44mod uint_macros; // import uint_impl!
45
46mod bfloat;
47mod complex;
48mod error;
49pub(crate) mod float_macros;
50#[cfg(not(no_fp_fmt_parse))]
51mod float_parse;
52mod nonzero;
53mod saturating;
54mod traits;
55mod wrapping;
56
57/// 100% perma-unstable
58#[doc(hidden)]
59pub mod niche_types;
60
61#[unstable(feature = "f16b", issue = "160630")]
62pub use bfloat::f16b;
63#[unstable(feature = "complex_numbers", issue = "154023")]
64pub use complex::Complex;
65#[stable(feature = "int_error_matching", since = "1.55.0")]
66pub use error::IntErrorKind;
67#[stable(feature = "rust1", since = "1.0.0")]
68pub use error::ParseIntError;
69#[stable(feature = "try_from", since = "1.34.0")]
70pub use error::TryFromIntError;
71#[unstable(feature = "extended_float_error_kind", issue = "164793")]
72#[cfg(not(no_fp_fmt_parse))]
73pub use float_parse::FloatErrorKind;
74#[stable(feature = "rust1", since = "1.0.0")]
75#[cfg(not(no_fp_fmt_parse))]
76pub use float_parse::ParseFloatError;
77#[stable(feature = "generic_nonzero", since = "1.79.0")]
78pub use nonzero::NonZero;
79#[unstable(
80 feature = "nonzero_internals",
81 reason = "implementation detail which may disappear or be replaced at any time",
82 issue = "none"
83)]
84pub use nonzero::ZeroablePrimitive;
85#[stable(feature = "signed_nonzero", since = "1.34.0")]
86pub use nonzero::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize};
87#[stable(feature = "nonzero", since = "1.28.0")]
88pub use nonzero::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize};
89#[stable(feature = "saturating_int_impl", since = "1.74.0")]
90pub use saturating::Saturating;
91#[stable(feature = "rust1", since = "1.0.0")]
92pub use wrapping::Wrapping;
93
94macro_rules! u8_xe_bytes_doc {
95 () => {
96 "
97
98**Note**: This function is meaningless on `u8`. Byte order does not exist as a
99concept for byte-sized integers. This function is only provided in symmetry
100with larger integer types.
101
102"
103 };
104}
105
106macro_rules! i8_xe_bytes_doc {
107 () => {
108 "
109
110**Note**: This function is meaningless on `i8`. Byte order does not exist as a
111concept for byte-sized integers. This function is only provided in symmetry
112with larger integer types. You can cast from and to `u8` using
113[`cast_signed`](u8::cast_signed) and [`cast_unsigned`](Self::cast_unsigned).
114
115"
116 };
117}
118
119macro_rules! usize_isize_to_xe_bytes_doc {
120 () => {
121 "
122
123**Note**: This function returns an array of length 2, 4 or 8 bytes
124depending on the target pointer size.
125
126"
127 };
128}
129
130macro_rules! usize_isize_from_xe_bytes_doc {
131 () => {
132 "
133
134**Note**: This function takes an array of length 2, 4 or 8 bytes
135depending on the target pointer size.
136
137"
138 };
139}
140
141macro_rules! midpoint_impl {
142 ($SelfT:ty, unsigned) => {
143 /// Calculates the midpoint (average) between `self` and `rhs`.
144 ///
145 /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
146 /// sufficiently-large unsigned integral type. This implies that the result is
147 /// always rounded towards zero and that no overflow will ever occur.
148 ///
149 /// # Examples
150 ///
151 /// ```
152 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
153 #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
154 /// ```
155 #[stable(feature = "num_midpoint", since = "1.85.0")]
156 #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
157 #[must_use = "this returns the result of the operation, \
158 without modifying the original"]
159 #[doc(alias = "average_floor")]
160 #[doc(alias = "average")]
161 #[inline]
162 pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
163 // Use the well known branchless algorithm from Hacker's Delight to compute
164 // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`.
165 ((self ^ rhs) >> 1) + (self & rhs)
166 }
167 };
168 ($SelfT:ty, signed) => {
169 /// Calculates the midpoint (average) between `self` and `rhs`.
170 ///
171 /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
172 /// sufficiently-large signed integral type. This implies that the result is
173 /// always rounded towards zero and that no overflow will ever occur.
174 ///
175 /// # Examples
176 ///
177 /// ```
178 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
179 #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")]
180 #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")]
181 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")]
182 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")]
183 /// ```
184 #[stable(feature = "num_midpoint_signed", since = "1.87.0")]
185 #[rustc_const_stable(feature = "num_midpoint_signed", since = "1.87.0")]
186 #[must_use = "this returns the result of the operation, \
187 without modifying the original"]
188 #[doc(alias = "average_floor")]
189 #[doc(alias = "average_ceil")]
190 #[doc(alias = "average")]
191 #[inline]
192 pub const fn midpoint(self, rhs: Self) -> Self {
193 // Use the well known branchless algorithm from Hacker's Delight to compute
194 // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`.
195 let t = ((self ^ rhs) >> 1) + (self & rhs);
196 // Except that it fails for integers whose sum is an odd negative number as
197 // their floor is one less than their average. So we adjust the result.
198 t + (if t < 0 { 1 } else { 0 } & (self ^ rhs))
199 }
200 };
201 ($SelfT:ty, $WideT:ty, unsigned) => {
202 /// Calculates the midpoint (average) between `self` and `rhs`.
203 ///
204 /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
205 /// sufficiently-large unsigned integral type. This implies that the result is
206 /// always rounded towards zero and that no overflow will ever occur.
207 ///
208 /// # Examples
209 ///
210 /// ```
211 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
212 #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".midpoint(4), 2);")]
213 /// ```
214 #[stable(feature = "num_midpoint", since = "1.85.0")]
215 #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
216 #[must_use = "this returns the result of the operation, \
217 without modifying the original"]
218 #[doc(alias = "average_floor")]
219 #[doc(alias = "average")]
220 #[inline]
221 pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
222 ((self as $WideT + rhs as $WideT) / 2) as $SelfT
223 }
224 };
225 ($SelfT:ty, $WideT:ty, signed) => {
226 /// Calculates the midpoint (average) between `self` and `rhs`.
227 ///
228 /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
229 /// sufficiently-large signed integral type. This implies that the result is
230 /// always rounded towards zero and that no overflow will ever occur.
231 ///
232 /// # Examples
233 ///
234 /// ```
235 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(4), 2);")]
236 #[doc = concat!("assert_eq!((-1", stringify!($SelfT), ").midpoint(2), 0);")]
237 #[doc = concat!("assert_eq!((-7", stringify!($SelfT), ").midpoint(0), -3);")]
238 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")]
239 #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")]
240 /// ```
241 #[stable(feature = "num_midpoint_signed", since = "1.87.0")]
242 #[rustc_const_stable(feature = "num_midpoint_signed", since = "1.87.0")]
243 #[must_use = "this returns the result of the operation, \
244 without modifying the original"]
245 #[doc(alias = "average_floor")]
246 #[doc(alias = "average_ceil")]
247 #[doc(alias = "average")]
248 #[inline]
249 pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
250 ((self as $WideT + rhs as $WideT) / 2) as $SelfT
251 }
252 };
253}
254
255macro_rules! widening_mul_impl {
256 ($SelfT:ty, $WideT:ty) => {
257 /// Widening multiplication. Computes `self * rhs`, widening to a larger integer.
258 ///
259 /// The returned value is always exact and can never overflow.
260 ///
261 /// Note that this method is semantically equivalent to [`carrying_mul`] with a
262 /// carry of zero, with the latter instead returning a tuple denoting the low and
263 /// high parts of the result. Consider using it instead if you need
264 /// interoperability with other big int helper functions, or if this method isn't
265 /// available for a given type.
266 ///
267 /// [`carrying_mul`]: Self::carrying_mul
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// #![feature(widening_mul)]
273 ///
274 #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(0_", stringify!($SelfT), "), 0);")]
275 #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), ", stringify!($SelfT), "::MAX as ", stringify!($WideT), " * ", stringify!($SelfT), "::MAX as ", stringify!($WideT), ");")]
276 /// ```
277 #[unstable(feature = "widening_mul", issue = "152016")]
278 #[rustc_const_unstable(feature = "widening_mul", issue = "152016")]
279 #[must_use = "this returns the result of the operation, \
280 without modifying the original"]
281 #[inline]
282 pub const fn widening_mul(self, rhs: Self) -> $WideT {
283 self as $WideT * rhs as $WideT
284 }
285 }
286}
287
288macro_rules! widening_carryless_mul_impl {
289 ($SelfT:ty, $WideT:ty) => {
290 /// Performs a widening carry-less multiplication.
291 ///
292 /// # Examples
293 ///
294 /// ```
295 /// #![feature(uint_carryless_mul)]
296 ///
297 #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_carryless_mul(",
298 stringify!($SelfT), "::MAX), ", stringify!($WideT), "::MAX / 3);")]
299 /// ```
300 #[rustc_const_unstable(feature = "uint_carryless_mul", issue = "152080")]
301 #[doc(alias = "clmul")]
302 #[unstable(feature = "uint_carryless_mul", issue = "152080")]
303 #[must_use = "this returns the result of the operation, \
304 without modifying the original"]
305 #[inline]
306 pub const fn widening_carryless_mul(self, rhs: $SelfT) -> $WideT {
307 (self as $WideT).carryless_mul(rhs as $WideT)
308 }
309 }
310}
311
312macro_rules! carrying_carryless_mul_impl {
313 (u128, u256) => {
314 carrying_carryless_mul_impl! { @internal u128 =>
315 pub const fn carrying_carryless_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
316 let x0 = self as u64;
317 let x1 = (self >> 64) as u64;
318 let y0 = rhs as u64;
319 let y1 = (rhs >> 64) as u64;
320
321 let z0 = u64::widening_carryless_mul(x0, y0);
322 let z2 = u64::widening_carryless_mul(x1, y1);
323
324 // The grade school algorithm would compute:
325 // z1 = x0y1 ^ x1y0
326
327 // Instead, Karatsuba first computes:
328 let z3 = u64::widening_carryless_mul(x0 ^ x1, y0 ^ y1);
329 // Since it distributes over XOR,
330 // z3 == x0y0 ^ x0y1 ^ x1y0 ^ x1y1
331 // |--| |---------| |--|
332 // == z0 ^ z1 ^ z2
333 // so we can compute z1 as
334 let z1 = z3 ^ z0 ^ z2;
335
336 let lo = z0 ^ (z1 << 64);
337 let hi = z2 ^ (z1 >> 64);
338
339 (lo ^ carry, hi)
340 }
341 }
342 };
343 ($SelfT:ty, $WideT:ty) => {
344 carrying_carryless_mul_impl! { @internal $SelfT =>
345 pub const fn carrying_carryless_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
346 // Can't use widening_carryless_mul because it's not implemented for usize.
347 let p = (self as $WideT).carryless_mul(rhs as $WideT);
348
349 let lo = (p as $SelfT);
350 let hi = (p >> Self::BITS) as $SelfT;
351
352 (lo ^ carry, hi)
353 }
354 }
355 };
356 (@internal $SelfT:ty => $($fn:tt)*) => {
357 /// Calculates the "full carryless multiplication" without the possibility to overflow.
358 ///
359 /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
360 /// of the result as two separate values, in that order.
361 ///
362 /// # Examples
363 ///
364 /// Please note that this example is shared among integer types, which is why `u8` is used.
365 ///
366 /// ```
367 /// #![feature(uint_carryless_mul)]
368 ///
369 /// assert_eq!(0b1000_0000u8.carrying_carryless_mul(0b1000_0000, 0b0000), (0, 0b0100_0000));
370 /// assert_eq!(0b1000_0000u8.carrying_carryless_mul(0b1000_0000, 0b1111), (0b1111, 0b0100_0000));
371 #[doc = concat!("assert_eq!(",
372 stringify!($SelfT), "::MAX.carrying_carryless_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ",
373 "(!(", stringify!($SelfT), "::MAX / 3), ", stringify!($SelfT), "::MAX / 3));"
374 )]
375 /// ```
376 #[rustc_const_unstable(feature = "uint_carryless_mul", issue = "152080")]
377 #[doc(alias = "clmul")]
378 #[unstable(feature = "uint_carryless_mul", issue = "152080")]
379 #[must_use = "this returns the result of the operation, \
380 without modifying the original"]
381 #[inline]
382 $($fn)*
383 }
384}
385
386impl i8 {
387 int_impl! {
388 Self = i8,
389 ActualT = i8,
390 UnsignedT = u8,
391 BITS = 8,
392 BITS_MINUS_ONE = 7,
393 Min = -128,
394 Max = 127,
395 rot = 2,
396 rot_op = "-0x7e",
397 rot_result = "0x0a",
398 swap_op = "0x12",
399 swapped = "0x12",
400 reversed = "0x48",
401 le_bytes = "[0x12]",
402 be_bytes = "[0x12]",
403 to_xe_bytes_doc = i8_xe_bytes_doc!(),
404 from_xe_bytes_doc = i8_xe_bytes_doc!(),
405 bound_condition = "",
406 }
407 midpoint_impl! { i8, i16, signed }
408 widening_mul_impl! { i8, i16 }
409}
410
411impl i16 {
412 int_impl! {
413 Self = i16,
414 ActualT = i16,
415 UnsignedT = u16,
416 BITS = 16,
417 BITS_MINUS_ONE = 15,
418 Min = -32768,
419 Max = 32767,
420 rot = 4,
421 rot_op = "-0x5ffd",
422 rot_result = "0x003a",
423 swap_op = "0x1234",
424 swapped = "0x3412",
425 reversed = "0x2c48",
426 le_bytes = "[0x34, 0x12]",
427 be_bytes = "[0x12, 0x34]",
428 to_xe_bytes_doc = "",
429 from_xe_bytes_doc = "",
430 bound_condition = "",
431 }
432 midpoint_impl! { i16, i32, signed }
433 widening_mul_impl! { i16, i32 }
434}
435
436impl i32 {
437 int_impl! {
438 Self = i32,
439 ActualT = i32,
440 UnsignedT = u32,
441 BITS = 32,
442 BITS_MINUS_ONE = 31,
443 Min = -2147483648,
444 Max = 2147483647,
445 rot = 8,
446 rot_op = "0x010000b3",
447 rot_result = "0x0000b301",
448 swap_op = "0x12345678",
449 swapped = "0x78563412",
450 reversed = "0x1e6a2c48",
451 le_bytes = "[0x78, 0x56, 0x34, 0x12]",
452 be_bytes = "[0x12, 0x34, 0x56, 0x78]",
453 to_xe_bytes_doc = "",
454 from_xe_bytes_doc = "",
455 bound_condition = "",
456 }
457 midpoint_impl! { i32, i64, signed }
458 widening_mul_impl! { i32, i64 }
459}
460
461impl i64 {
462 int_impl! {
463 Self = i64,
464 ActualT = i64,
465 UnsignedT = u64,
466 BITS = 64,
467 BITS_MINUS_ONE = 63,
468 Min = -9223372036854775808,
469 Max = 9223372036854775807,
470 rot = 12,
471 rot_op = "0x0aa00000000006e1",
472 rot_result = "0x00000000006e10aa",
473 swap_op = "0x1234567890123456",
474 swapped = "0x5634129078563412",
475 reversed = "0x6a2c48091e6a2c48",
476 le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
477 be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
478 to_xe_bytes_doc = "",
479 from_xe_bytes_doc = "",
480 bound_condition = "",
481 }
482 midpoint_impl! { i64, signed }
483 widening_mul_impl! { i64, i128 }
484}
485
486impl i128 {
487 int_impl! {
488 Self = i128,
489 ActualT = i128,
490 UnsignedT = u128,
491 BITS = 128,
492 BITS_MINUS_ONE = 127,
493 Min = -170141183460469231731687303715884105728,
494 Max = 170141183460469231731687303715884105727,
495 rot = 16,
496 rot_op = "0x13f40000000000000000000000004f76",
497 rot_result = "0x0000000000000000000000004f7613f4",
498 swap_op = "0x12345678901234567890123456789012",
499 swapped = "0x12907856341290785634129078563412",
500 reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
501 le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
502 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
503 be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
504 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
505 to_xe_bytes_doc = "",
506 from_xe_bytes_doc = "",
507 bound_condition = "",
508 }
509 midpoint_impl! { i128, signed }
510}
511
512#[doc(auto_cfg = false)]
513#[cfg(target_pointer_width = "16")]
514impl isize {
515 int_impl! {
516 Self = isize,
517 ActualT = i16,
518 UnsignedT = usize,
519 BITS = 16,
520 BITS_MINUS_ONE = 15,
521 Min = -32768,
522 Max = 32767,
523 rot = 4,
524 rot_op = "-0x5ffd",
525 rot_result = "0x003a",
526 swap_op = "0x1234",
527 swapped = "0x3412",
528 reversed = "0x2c48",
529 le_bytes = "[0x34, 0x12]",
530 be_bytes = "[0x12, 0x34]",
531 to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
532 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
533 bound_condition = " on 16-bit targets",
534 }
535 midpoint_impl! { isize, i32, signed }
536}
537
538#[doc(auto_cfg = false)]
539#[cfg(target_pointer_width = "32")]
540impl isize {
541 int_impl! {
542 Self = isize,
543 ActualT = i32,
544 UnsignedT = usize,
545 BITS = 32,
546 BITS_MINUS_ONE = 31,
547 Min = -2147483648,
548 Max = 2147483647,
549 rot = 8,
550 rot_op = "0x010000b3",
551 rot_result = "0x0000b301",
552 swap_op = "0x12345678",
553 swapped = "0x78563412",
554 reversed = "0x1e6a2c48",
555 le_bytes = "[0x78, 0x56, 0x34, 0x12]",
556 be_bytes = "[0x12, 0x34, 0x56, 0x78]",
557 to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
558 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
559 bound_condition = " on 32-bit targets",
560 }
561 midpoint_impl! { isize, i64, signed }
562}
563
564#[doc(auto_cfg = false)]
565#[cfg(target_pointer_width = "64")]
566impl isize {
567 int_impl! {
568 Self = isize,
569 ActualT = i64,
570 UnsignedT = usize,
571 BITS = 64,
572 BITS_MINUS_ONE = 63,
573 Min = -9223372036854775808,
574 Max = 9223372036854775807,
575 rot = 12,
576 rot_op = "0x0aa00000000006e1",
577 rot_result = "0x00000000006e10aa",
578 swap_op = "0x1234567890123456",
579 swapped = "0x5634129078563412",
580 reversed = "0x6a2c48091e6a2c48",
581 le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
582 be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
583 to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
584 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
585 bound_condition = " on 64-bit targets",
586 }
587 midpoint_impl! { isize, signed }
588}
589
590/// If the bit selected by this mask is set, ascii is lower case.
591const ASCII_CASE_MASK: u8 = 0b0010_0000;
592
593impl u8 {
594 uint_impl! {
595 Self = u8,
596 ActualT = u8,
597 SignedT = i8,
598 BITS = 8,
599 BITS_MINUS_ONE = 7,
600 MAX = 255,
601 rot = 2,
602 rot_op = "0x82",
603 rot_result = "0x0a",
604 fsh_op = "0x36",
605 fshl_result = "0x08",
606 fshr_result = "0x8d",
607 clmul_lhs = "0x12",
608 clmul_rhs = "0x34",
609 clmul_result = "0x28",
610 swap_op = "0x12",
611 swapped = "0x12",
612 reversed = "0x48",
613 le_bytes = "[0x12]",
614 be_bytes = "[0x12]",
615 to_xe_bytes_doc = u8_xe_bytes_doc!(),
616 from_xe_bytes_doc = u8_xe_bytes_doc!(),
617 bound_condition = "",
618 }
619 midpoint_impl! { u8, u16, unsigned }
620 widening_mul_impl! { u8, u16 }
621 widening_carryless_mul_impl! { u8, u16 }
622 carrying_carryless_mul_impl! { u8, u16 }
623
624 /// Checks if the value is within the ASCII range.
625 ///
626 /// # Examples
627 ///
628 /// ```
629 /// let ascii = 97u8;
630 /// let non_ascii = 150u8;
631 ///
632 /// assert!(ascii.is_ascii());
633 /// assert!(!non_ascii.is_ascii());
634 /// ```
635 #[must_use]
636 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
637 #[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")]
638 #[inline]
639 pub const fn is_ascii(&self) -> bool {
640 *self <= 127
641 }
642
643 /// If the value of this byte is within the ASCII range, returns it as an
644 /// [ASCII character](ascii::Char). Otherwise, returns `None`.
645 #[must_use]
646 #[unstable(feature = "ascii_char", issue = "110998")]
647 #[inline]
648 pub const fn as_ascii(&self) -> Option<ascii::Char> {
649 ascii::Char::from_u8(*self)
650 }
651
652 /// Converts this byte to an [ASCII character](ascii::Char), without
653 /// checking whether or not it's valid.
654 ///
655 /// # Safety
656 ///
657 /// This byte must be valid ASCII, or else this is UB.
658 #[must_use]
659 #[unstable(feature = "ascii_char", issue = "110998")]
660 #[inline]
661 pub const unsafe fn as_ascii_unchecked(&self) -> ascii::Char {
662 assert_unsafe_precondition!(
663 check_library_ub,
664 "as_ascii_unchecked requires that the byte is valid ASCII",
665 (it: &u8 = self) => it.is_ascii()
666 );
667
668 // SAFETY: the caller promised that this byte is ASCII.
669 unsafe { ascii::Char::from_u8_unchecked(*self) }
670 }
671
672 /// Makes a copy of the value in its ASCII upper case equivalent.
673 ///
674 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
675 /// but non-ASCII letters are unchanged.
676 ///
677 /// To uppercase the value in-place, use [`make_ascii_uppercase`].
678 ///
679 /// # Examples
680 ///
681 /// ```
682 /// let lowercase_a = 97u8;
683 ///
684 /// assert_eq!(65, lowercase_a.to_ascii_uppercase());
685 /// ```
686 ///
687 /// [`make_ascii_uppercase`]: Self::make_ascii_uppercase
688 #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
689 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
690 #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
691 #[inline]
692 pub const fn to_ascii_uppercase(&self) -> u8 {
693 // Toggle the 6th bit if this is a lowercase letter
694 *self ^ ((self.is_ascii_lowercase() as u8) * ASCII_CASE_MASK)
695 }
696
697 /// Makes a copy of the value in its ASCII lower case equivalent.
698 ///
699 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
700 /// but non-ASCII letters are unchanged.
701 ///
702 /// To lowercase the value in-place, use [`make_ascii_lowercase`].
703 ///
704 /// # Examples
705 ///
706 /// ```
707 /// let uppercase_a = 65u8;
708 ///
709 /// assert_eq!(97, uppercase_a.to_ascii_lowercase());
710 /// ```
711 ///
712 /// [`make_ascii_lowercase`]: Self::make_ascii_lowercase
713 #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
714 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
715 #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
716 #[inline]
717 pub const fn to_ascii_lowercase(&self) -> u8 {
718 // Set the 6th bit if this is an uppercase letter
719 *self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK)
720 }
721
722 /// Assumes self is ascii
723 #[inline]
724 pub(crate) const fn ascii_change_case_unchecked(&self) -> u8 {
725 *self ^ ASCII_CASE_MASK
726 }
727
728 /// Checks that two values are an ASCII case-insensitive match.
729 ///
730 /// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
731 ///
732 /// # Examples
733 ///
734 /// ```
735 /// let lowercase_a = 97u8;
736 /// let uppercase_a = 65u8;
737 ///
738 /// assert!(lowercase_a.eq_ignore_ascii_case(&uppercase_a));
739 /// ```
740 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
741 #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
742 #[expect(clippy::manual_ignore_case_cmp, reason = "implements eq_ignore_ascii_case")]
743 #[inline]
744 pub const fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
745 self.to_ascii_lowercase() == other.to_ascii_lowercase()
746 }
747
748 /// Converts this value to its ASCII upper case equivalent in-place.
749 ///
750 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
751 /// but non-ASCII letters are unchanged.
752 ///
753 /// To return a new uppercased value without modifying the existing one, use
754 /// [`to_ascii_uppercase`].
755 ///
756 /// # Examples
757 ///
758 /// ```
759 /// let mut byte = b'a';
760 ///
761 /// byte.make_ascii_uppercase();
762 ///
763 /// assert_eq!(b'A', byte);
764 /// ```
765 ///
766 /// [`to_ascii_uppercase`]: Self::to_ascii_uppercase
767 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
768 #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")]
769 #[inline]
770 pub const fn make_ascii_uppercase(&mut self) {
771 *self = self.to_ascii_uppercase();
772 }
773
774 /// Converts this value to its ASCII lower case equivalent in-place.
775 ///
776 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
777 /// but non-ASCII letters are unchanged.
778 ///
779 /// To return a new lowercased value without modifying the existing one, use
780 /// [`to_ascii_lowercase`].
781 ///
782 /// # Examples
783 ///
784 /// ```
785 /// let mut byte = b'A';
786 ///
787 /// byte.make_ascii_lowercase();
788 ///
789 /// assert_eq!(b'a', byte);
790 /// ```
791 ///
792 /// [`to_ascii_lowercase`]: Self::to_ascii_lowercase
793 #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
794 #[rustc_const_stable(feature = "const_make_ascii", since = "1.84.0")]
795 #[inline]
796 pub const fn make_ascii_lowercase(&mut self) {
797 *self = self.to_ascii_lowercase();
798 }
799
800 /// Checks if the value is an ASCII alphabetic character:
801 ///
802 /// - U+0041 'A' ..= U+005A 'Z', or
803 /// - U+0061 'a' ..= U+007A 'z'.
804 ///
805 /// # Examples
806 ///
807 /// ```
808 /// let uppercase_a = b'A';
809 /// let uppercase_g = b'G';
810 /// let a = b'a';
811 /// let g = b'g';
812 /// let zero = b'0';
813 /// let percent = b'%';
814 /// let space = b' ';
815 /// let lf = b'\n';
816 /// let esc = b'\x1b';
817 ///
818 /// assert!(uppercase_a.is_ascii_alphabetic());
819 /// assert!(uppercase_g.is_ascii_alphabetic());
820 /// assert!(a.is_ascii_alphabetic());
821 /// assert!(g.is_ascii_alphabetic());
822 /// assert!(!zero.is_ascii_alphabetic());
823 /// assert!(!percent.is_ascii_alphabetic());
824 /// assert!(!space.is_ascii_alphabetic());
825 /// assert!(!lf.is_ascii_alphabetic());
826 /// assert!(!esc.is_ascii_alphabetic());
827 /// ```
828 #[must_use]
829 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
830 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
831 #[inline]
832 pub const fn is_ascii_alphabetic(&self) -> bool {
833 matches!(*self, b'A'..=b'Z' | b'a'..=b'z')
834 }
835
836 /// Checks if the value is an ASCII uppercase character:
837 /// U+0041 'A' ..= U+005A 'Z'.
838 ///
839 /// # Examples
840 ///
841 /// ```
842 /// let uppercase_a = b'A';
843 /// let uppercase_g = b'G';
844 /// let a = b'a';
845 /// let g = b'g';
846 /// let zero = b'0';
847 /// let percent = b'%';
848 /// let space = b' ';
849 /// let lf = b'\n';
850 /// let esc = b'\x1b';
851 ///
852 /// assert!(uppercase_a.is_ascii_uppercase());
853 /// assert!(uppercase_g.is_ascii_uppercase());
854 /// assert!(!a.is_ascii_uppercase());
855 /// assert!(!g.is_ascii_uppercase());
856 /// assert!(!zero.is_ascii_uppercase());
857 /// assert!(!percent.is_ascii_uppercase());
858 /// assert!(!space.is_ascii_uppercase());
859 /// assert!(!lf.is_ascii_uppercase());
860 /// assert!(!esc.is_ascii_uppercase());
861 /// ```
862 #[must_use]
863 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
864 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
865 #[inline]
866 pub const fn is_ascii_uppercase(&self) -> bool {
867 matches!(*self, b'A'..=b'Z')
868 }
869
870 /// Checks if the value is an ASCII lowercase character:
871 /// U+0061 'a' ..= U+007A 'z'.
872 ///
873 /// # Examples
874 ///
875 /// ```
876 /// let uppercase_a = b'A';
877 /// let uppercase_g = b'G';
878 /// let a = b'a';
879 /// let g = b'g';
880 /// let zero = b'0';
881 /// let percent = b'%';
882 /// let space = b' ';
883 /// let lf = b'\n';
884 /// let esc = b'\x1b';
885 ///
886 /// assert!(!uppercase_a.is_ascii_lowercase());
887 /// assert!(!uppercase_g.is_ascii_lowercase());
888 /// assert!(a.is_ascii_lowercase());
889 /// assert!(g.is_ascii_lowercase());
890 /// assert!(!zero.is_ascii_lowercase());
891 /// assert!(!percent.is_ascii_lowercase());
892 /// assert!(!space.is_ascii_lowercase());
893 /// assert!(!lf.is_ascii_lowercase());
894 /// assert!(!esc.is_ascii_lowercase());
895 /// ```
896 #[must_use]
897 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
898 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
899 #[inline]
900 pub const fn is_ascii_lowercase(&self) -> bool {
901 matches!(*self, b'a'..=b'z')
902 }
903
904 /// Checks if the value is an ASCII alphanumeric character:
905 ///
906 /// - U+0041 'A' ..= U+005A 'Z', or
907 /// - U+0061 'a' ..= U+007A 'z', or
908 /// - U+0030 '0' ..= U+0039 '9'.
909 ///
910 /// # Examples
911 ///
912 /// ```
913 /// let uppercase_a = b'A';
914 /// let uppercase_g = b'G';
915 /// let a = b'a';
916 /// let g = b'g';
917 /// let zero = b'0';
918 /// let percent = b'%';
919 /// let space = b' ';
920 /// let lf = b'\n';
921 /// let esc = b'\x1b';
922 ///
923 /// assert!(uppercase_a.is_ascii_alphanumeric());
924 /// assert!(uppercase_g.is_ascii_alphanumeric());
925 /// assert!(a.is_ascii_alphanumeric());
926 /// assert!(g.is_ascii_alphanumeric());
927 /// assert!(zero.is_ascii_alphanumeric());
928 /// assert!(!percent.is_ascii_alphanumeric());
929 /// assert!(!space.is_ascii_alphanumeric());
930 /// assert!(!lf.is_ascii_alphanumeric());
931 /// assert!(!esc.is_ascii_alphanumeric());
932 /// ```
933 #[must_use]
934 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
935 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
936 #[inline]
937 pub const fn is_ascii_alphanumeric(&self) -> bool {
938 matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'Z') | matches!(*self, b'a'..=b'z')
939 }
940
941 /// Checks if the value is an ASCII decimal digit:
942 /// U+0030 '0' ..= U+0039 '9'.
943 ///
944 /// # Examples
945 ///
946 /// ```
947 /// let uppercase_a = b'A';
948 /// let uppercase_g = b'G';
949 /// let a = b'a';
950 /// let g = b'g';
951 /// let zero = b'0';
952 /// let percent = b'%';
953 /// let space = b' ';
954 /// let lf = b'\n';
955 /// let esc = b'\x1b';
956 ///
957 /// assert!(!uppercase_a.is_ascii_digit());
958 /// assert!(!uppercase_g.is_ascii_digit());
959 /// assert!(!a.is_ascii_digit());
960 /// assert!(!g.is_ascii_digit());
961 /// assert!(zero.is_ascii_digit());
962 /// assert!(!percent.is_ascii_digit());
963 /// assert!(!space.is_ascii_digit());
964 /// assert!(!lf.is_ascii_digit());
965 /// assert!(!esc.is_ascii_digit());
966 /// ```
967 #[must_use]
968 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
969 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
970 #[inline]
971 pub const fn is_ascii_digit(&self) -> bool {
972 matches!(*self, b'0'..=b'9')
973 }
974
975 /// Checks if the value is an ASCII octal digit:
976 /// U+0030 '0' ..= U+0037 '7'.
977 ///
978 /// # Examples
979 ///
980 /// ```
981 /// #![feature(is_ascii_octdigit)]
982 ///
983 /// let uppercase_a = b'A';
984 /// let a = b'a';
985 /// let zero = b'0';
986 /// let seven = b'7';
987 /// let nine = b'9';
988 /// let percent = b'%';
989 /// let lf = b'\n';
990 ///
991 /// assert!(!uppercase_a.is_ascii_octdigit());
992 /// assert!(!a.is_ascii_octdigit());
993 /// assert!(zero.is_ascii_octdigit());
994 /// assert!(seven.is_ascii_octdigit());
995 /// assert!(!nine.is_ascii_octdigit());
996 /// assert!(!percent.is_ascii_octdigit());
997 /// assert!(!lf.is_ascii_octdigit());
998 /// ```
999 #[must_use]
1000 #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
1001 #[inline]
1002 pub const fn is_ascii_octdigit(&self) -> bool {
1003 matches!(*self, b'0'..=b'7')
1004 }
1005
1006 /// Checks if the value is an ASCII hexadecimal digit:
1007 ///
1008 /// - U+0030 '0' ..= U+0039 '9', or
1009 /// - U+0041 'A' ..= U+0046 'F', or
1010 /// - U+0061 'a' ..= U+0066 'f'.
1011 ///
1012 /// # Examples
1013 ///
1014 /// ```
1015 /// let uppercase_a = b'A';
1016 /// let uppercase_g = b'G';
1017 /// let a = b'a';
1018 /// let g = b'g';
1019 /// let zero = b'0';
1020 /// let percent = b'%';
1021 /// let space = b' ';
1022 /// let lf = b'\n';
1023 /// let esc = b'\x1b';
1024 ///
1025 /// assert!(uppercase_a.is_ascii_hexdigit());
1026 /// assert!(!uppercase_g.is_ascii_hexdigit());
1027 /// assert!(a.is_ascii_hexdigit());
1028 /// assert!(!g.is_ascii_hexdigit());
1029 /// assert!(zero.is_ascii_hexdigit());
1030 /// assert!(!percent.is_ascii_hexdigit());
1031 /// assert!(!space.is_ascii_hexdigit());
1032 /// assert!(!lf.is_ascii_hexdigit());
1033 /// assert!(!esc.is_ascii_hexdigit());
1034 /// ```
1035 #[must_use]
1036 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1037 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
1038 #[inline]
1039 pub const fn is_ascii_hexdigit(&self) -> bool {
1040 matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'F') | matches!(*self, b'a'..=b'f')
1041 }
1042
1043 /// Checks if the value is an ASCII punctuation or symbol character
1044 /// (i.e. not alphanumeric, whitespace, or control):
1045 ///
1046 /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or
1047 /// - U+003A ..= U+0040 `: ; < = > ? @`, or
1048 /// - U+005B ..= U+0060 `` [ \ ] ^ _ ` ``, or
1049 /// - U+007B ..= U+007E `{ | } ~`
1050 ///
1051 /// # Examples
1052 ///
1053 /// ```
1054 /// let uppercase_a = b'A';
1055 /// let uppercase_g = b'G';
1056 /// let a = b'a';
1057 /// let g = b'g';
1058 /// let zero = b'0';
1059 /// let percent = b'%';
1060 /// let space = b' ';
1061 /// let lf = b'\n';
1062 /// let esc = b'\x1b';
1063 ///
1064 /// assert!(!uppercase_a.is_ascii_punctuation());
1065 /// assert!(!uppercase_g.is_ascii_punctuation());
1066 /// assert!(!a.is_ascii_punctuation());
1067 /// assert!(!g.is_ascii_punctuation());
1068 /// assert!(!zero.is_ascii_punctuation());
1069 /// assert!(percent.is_ascii_punctuation());
1070 /// assert!(!space.is_ascii_punctuation());
1071 /// assert!(!lf.is_ascii_punctuation());
1072 /// assert!(!esc.is_ascii_punctuation());
1073 /// ```
1074 #[must_use]
1075 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1076 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
1077 #[inline]
1078 pub const fn is_ascii_punctuation(&self) -> bool {
1079 matches!(*self, b'!'..=b'/')
1080 | matches!(*self, b':'..=b'@')
1081 | matches!(*self, b'['..=b'`')
1082 | matches!(*self, b'{'..=b'~')
1083 }
1084
1085 /// Checks if the value is an ASCII graphic character
1086 /// (i.e. not whitespace or control):
1087 /// U+0021 '!' ..= U+007E '~'.
1088 ///
1089 /// # Examples
1090 ///
1091 /// ```
1092 /// let uppercase_a = b'A';
1093 /// let uppercase_g = b'G';
1094 /// let a = b'a';
1095 /// let g = b'g';
1096 /// let zero = b'0';
1097 /// let percent = b'%';
1098 /// let space = b' ';
1099 /// let lf = b'\n';
1100 /// let esc = b'\x1b';
1101 ///
1102 /// assert!(uppercase_a.is_ascii_graphic());
1103 /// assert!(uppercase_g.is_ascii_graphic());
1104 /// assert!(a.is_ascii_graphic());
1105 /// assert!(g.is_ascii_graphic());
1106 /// assert!(zero.is_ascii_graphic());
1107 /// assert!(percent.is_ascii_graphic());
1108 /// assert!(!space.is_ascii_graphic());
1109 /// assert!(!lf.is_ascii_graphic());
1110 /// assert!(!esc.is_ascii_graphic());
1111 /// ```
1112 #[must_use]
1113 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1114 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
1115 #[inline]
1116 pub const fn is_ascii_graphic(&self) -> bool {
1117 matches!(*self, b'!'..=b'~')
1118 }
1119
1120 /// Checks if the value is an ASCII whitespace character:
1121 /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
1122 /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
1123 ///
1124 /// **Warning:** Because the list above excludes U+000B VERTICAL TAB,
1125 /// `b.is_ascii_whitespace()` is **not** equivalent to `char::from(b).is_whitespace()`.
1126 ///
1127 /// Rust uses the WhatWG Infra Standard's [definition of ASCII
1128 /// whitespace][infra-aw]. There are several other definitions in
1129 /// wide use. For instance, [the POSIX locale][pct] includes
1130 /// U+000B VERTICAL TAB as well as all the above characters,
1131 /// but—from the very same specification—[the default rule for
1132 /// "field splitting" in the Bourne shell][bfs] considers *only*
1133 /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
1134 ///
1135 /// If you are writing a program that will process an existing
1136 /// file format, check what that format's definition of whitespace is
1137 /// before using this function.
1138 ///
1139 /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
1140 /// [pct]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01
1141 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_06_05
1142 ///
1143 /// # Examples
1144 ///
1145 /// ```
1146 /// let uppercase_a = b'A';
1147 /// let uppercase_g = b'G';
1148 /// let a = b'a';
1149 /// let g = b'g';
1150 /// let zero = b'0';
1151 /// let percent = b'%';
1152 /// let space = b' ';
1153 /// let lf = b'\n';
1154 /// let esc = b'\x1b';
1155 ///
1156 /// assert!(!uppercase_a.is_ascii_whitespace());
1157 /// assert!(!uppercase_g.is_ascii_whitespace());
1158 /// assert!(!a.is_ascii_whitespace());
1159 /// assert!(!g.is_ascii_whitespace());
1160 /// assert!(!zero.is_ascii_whitespace());
1161 /// assert!(!percent.is_ascii_whitespace());
1162 /// assert!(space.is_ascii_whitespace());
1163 /// assert!(lf.is_ascii_whitespace());
1164 /// assert!(!esc.is_ascii_whitespace());
1165 /// ```
1166 #[must_use]
1167 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1168 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
1169 #[inline]
1170 pub const fn is_ascii_whitespace(&self) -> bool {
1171 matches!(*self, b'\t' | b'\n' | b'\x0C' | b'\r' | b' ')
1172 }
1173
1174 /// Checks if the value is an ASCII control character:
1175 /// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE.
1176 /// Note that most ASCII whitespace characters are control
1177 /// characters, but SPACE is not.
1178 ///
1179 /// # Examples
1180 ///
1181 /// ```
1182 /// let uppercase_a = b'A';
1183 /// let uppercase_g = b'G';
1184 /// let a = b'a';
1185 /// let g = b'g';
1186 /// let zero = b'0';
1187 /// let percent = b'%';
1188 /// let space = b' ';
1189 /// let lf = b'\n';
1190 /// let esc = b'\x1b';
1191 ///
1192 /// assert!(!uppercase_a.is_ascii_control());
1193 /// assert!(!uppercase_g.is_ascii_control());
1194 /// assert!(!a.is_ascii_control());
1195 /// assert!(!g.is_ascii_control());
1196 /// assert!(!zero.is_ascii_control());
1197 /// assert!(!percent.is_ascii_control());
1198 /// assert!(!space.is_ascii_control());
1199 /// assert!(lf.is_ascii_control());
1200 /// assert!(esc.is_ascii_control());
1201 /// ```
1202 #[must_use]
1203 #[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
1204 #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
1205 #[inline]
1206 pub const fn is_ascii_control(&self) -> bool {
1207 matches!(*self, b'\0'..=b'\x1F' | b'\x7F')
1208 }
1209
1210 /// Returns an iterator that produces an escaped version of a `u8`,
1211 /// treating it as an ASCII character.
1212 ///
1213 /// The behavior is identical to [`ascii::escape_default`].
1214 ///
1215 /// # Examples
1216 ///
1217 /// ```
1218 /// assert_eq!("0", b'0'.escape_ascii().to_string());
1219 /// assert_eq!("\\t", b'\t'.escape_ascii().to_string());
1220 /// assert_eq!("\\r", b'\r'.escape_ascii().to_string());
1221 /// assert_eq!("\\n", b'\n'.escape_ascii().to_string());
1222 /// assert_eq!("\\'", b'\''.escape_ascii().to_string());
1223 /// assert_eq!("\\\"", b'"'.escape_ascii().to_string());
1224 /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string());
1225 /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string());
1226 /// ```
1227 #[must_use = "this returns the escaped byte as an iterator, \
1228 without modifying the original"]
1229 #[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
1230 #[inline]
1231 pub fn escape_ascii(self) -> ascii::EscapeDefault {
1232 ascii::escape_default(self)
1233 }
1234
1235 #[inline]
1236 pub(crate) const fn is_utf8_char_boundary(self) -> bool {
1237 // This is bit magic equivalent to: b < 128 || b >= 192
1238 (self as i8) >= -0x40
1239 }
1240}
1241
1242impl u16 {
1243 uint_impl! {
1244 Self = u16,
1245 ActualT = u16,
1246 SignedT = i16,
1247 BITS = 16,
1248 BITS_MINUS_ONE = 15,
1249 MAX = 65535,
1250 rot = 4,
1251 rot_op = "0xa003",
1252 rot_result = "0x003a",
1253 fsh_op = "0x02de",
1254 fshl_result = "0x0030",
1255 fshr_result = "0x302d",
1256 clmul_lhs = "0x9012",
1257 clmul_rhs = "0xcd34",
1258 clmul_result = "0x0928",
1259 swap_op = "0x1234",
1260 swapped = "0x3412",
1261 reversed = "0x2c48",
1262 le_bytes = "[0x34, 0x12]",
1263 be_bytes = "[0x12, 0x34]",
1264 to_xe_bytes_doc = "",
1265 from_xe_bytes_doc = "",
1266 bound_condition = "",
1267 }
1268 midpoint_impl! { u16, u32, unsigned }
1269 widening_mul_impl! { u16, u32 }
1270 widening_carryless_mul_impl! { u16, u32 }
1271 carrying_carryless_mul_impl! { u16, u32 }
1272
1273 /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
1274 ///
1275 /// # Examples
1276 ///
1277 /// ```
1278 /// #![feature(utf16_extra)]
1279 ///
1280 /// let low_non_surrogate = 0xA000u16;
1281 /// let low_surrogate = 0xD800u16;
1282 /// let high_surrogate = 0xDC00u16;
1283 /// let high_non_surrogate = 0xE000u16;
1284 ///
1285 /// assert!(!low_non_surrogate.is_utf16_surrogate());
1286 /// assert!(low_surrogate.is_utf16_surrogate());
1287 /// assert!(high_surrogate.is_utf16_surrogate());
1288 /// assert!(!high_non_surrogate.is_utf16_surrogate());
1289 /// ```
1290 #[must_use]
1291 #[unstable(feature = "utf16_extra", issue = "94919")]
1292 #[inline]
1293 pub const fn is_utf16_surrogate(self) -> bool {
1294 matches!(self, 0xD800..=0xDFFF)
1295 }
1296}
1297
1298impl u32 {
1299 uint_impl! {
1300 Self = u32,
1301 ActualT = u32,
1302 SignedT = i32,
1303 BITS = 32,
1304 BITS_MINUS_ONE = 31,
1305 MAX = 4294967295,
1306 rot = 8,
1307 rot_op = "0x010000b3",
1308 rot_result = "0x0000b301",
1309 fsh_op = "0x2fe78e45",
1310 fshl_result = "0x0000b32f",
1311 fshr_result = "0xb32fe78e",
1312 clmul_lhs = "0x56789012",
1313 clmul_rhs = "0xf52ecd34",
1314 clmul_result = "0x9b980928",
1315 swap_op = "0x12345678",
1316 swapped = "0x78563412",
1317 reversed = "0x1e6a2c48",
1318 le_bytes = "[0x78, 0x56, 0x34, 0x12]",
1319 be_bytes = "[0x12, 0x34, 0x56, 0x78]",
1320 to_xe_bytes_doc = "",
1321 from_xe_bytes_doc = "",
1322 bound_condition = "",
1323 }
1324 midpoint_impl! { u32, u64, unsigned }
1325 widening_mul_impl! { u32, u64 }
1326 widening_carryless_mul_impl! { u32, u64 }
1327 carrying_carryless_mul_impl! { u32, u64 }
1328}
1329
1330impl u64 {
1331 uint_impl! {
1332 Self = u64,
1333 ActualT = u64,
1334 SignedT = i64,
1335 BITS = 64,
1336 BITS_MINUS_ONE = 63,
1337 MAX = 18446744073709551615,
1338 rot = 12,
1339 rot_op = "0x0aa00000000006e1",
1340 rot_result = "0x00000000006e10aa",
1341 fsh_op = "0x2fe78e45983acd98",
1342 fshl_result = "0x00000000006e12fe",
1343 fshr_result = "0x6e12fe78e45983ac",
1344 clmul_lhs = "0x7890123456789012",
1345 clmul_rhs = "0xdd358416f52ecd34",
1346 clmul_result = "0x0a6299579b980928",
1347 swap_op = "0x1234567890123456",
1348 swapped = "0x5634129078563412",
1349 reversed = "0x6a2c48091e6a2c48",
1350 le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
1351 be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
1352 to_xe_bytes_doc = "",
1353 from_xe_bytes_doc = "",
1354 bound_condition = "",
1355 }
1356 midpoint_impl! { u64, u128, unsigned }
1357 widening_mul_impl! { u64, u128 }
1358 widening_carryless_mul_impl! { u64, u128 }
1359 carrying_carryless_mul_impl! { u64, u128 }
1360}
1361
1362impl u128 {
1363 uint_impl! {
1364 Self = u128,
1365 ActualT = u128,
1366 SignedT = i128,
1367 BITS = 128,
1368 BITS_MINUS_ONE = 127,
1369 MAX = 340282366920938463463374607431768211455,
1370 rot = 16,
1371 rot_op = "0x13f40000000000000000000000004f76",
1372 rot_result = "0x0000000000000000000000004f7613f4",
1373 fsh_op = "0x02fe78e45983acd98039000008736273",
1374 fshl_result = "0x0000000000000000000000004f7602fe",
1375 fshr_result = "0x4f7602fe78e45983acd9803900000873",
1376 clmul_lhs = "0x12345678901234567890123456789012",
1377 clmul_rhs = "0x4317e40ab4ddcf05dd358416f52ecd34",
1378 clmul_result = "0xb9cf660de35d0c170a6299579b980928",
1379 swap_op = "0x12345678901234567890123456789012",
1380 swapped = "0x12907856341290785634129078563412",
1381 reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
1382 le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
1383 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
1384 be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
1385 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
1386 to_xe_bytes_doc = "",
1387 from_xe_bytes_doc = "",
1388 bound_condition = "",
1389 }
1390 midpoint_impl! { u128, unsigned }
1391 carrying_carryless_mul_impl! { u128, u256 }
1392}
1393
1394#[doc(auto_cfg = false)]
1395#[cfg(target_pointer_width = "16")]
1396impl usize {
1397 uint_impl! {
1398 Self = usize,
1399 ActualT = u16,
1400 SignedT = isize,
1401 BITS = 16,
1402 BITS_MINUS_ONE = 15,
1403 MAX = 65535,
1404 rot = 4,
1405 rot_op = "0xa003",
1406 rot_result = "0x003a",
1407 fsh_op = "0x02de",
1408 fshl_result = "0x0030",
1409 fshr_result = "0x302d",
1410 clmul_lhs = "0x9012",
1411 clmul_rhs = "0xcd34",
1412 clmul_result = "0x0928",
1413 swap_op = "0x1234",
1414 swapped = "0x3412",
1415 reversed = "0x2c48",
1416 le_bytes = "[0x34, 0x12]",
1417 be_bytes = "[0x12, 0x34]",
1418 to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
1419 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
1420 bound_condition = " on 16-bit targets",
1421 }
1422 midpoint_impl! { usize, u32, unsigned }
1423 carrying_carryless_mul_impl! { usize, u32 }
1424}
1425
1426#[doc(auto_cfg = false)]
1427#[cfg(target_pointer_width = "32")]
1428impl usize {
1429 uint_impl! {
1430 Self = usize,
1431 ActualT = u32,
1432 SignedT = isize,
1433 BITS = 32,
1434 BITS_MINUS_ONE = 31,
1435 MAX = 4294967295,
1436 rot = 8,
1437 rot_op = "0x010000b3",
1438 rot_result = "0x0000b301",
1439 fsh_op = "0x2fe78e45",
1440 fshl_result = "0x0000b32f",
1441 fshr_result = "0xb32fe78e",
1442 clmul_lhs = "0x56789012",
1443 clmul_rhs = "0xf52ecd34",
1444 clmul_result = "0x9b980928",
1445 swap_op = "0x12345678",
1446 swapped = "0x78563412",
1447 reversed = "0x1e6a2c48",
1448 le_bytes = "[0x78, 0x56, 0x34, 0x12]",
1449 be_bytes = "[0x12, 0x34, 0x56, 0x78]",
1450 to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
1451 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
1452 bound_condition = " on 32-bit targets",
1453 }
1454 midpoint_impl! { usize, u64, unsigned }
1455 carrying_carryless_mul_impl! { usize, u64 }
1456}
1457
1458#[doc(auto_cfg = false)]
1459#[cfg(target_pointer_width = "64")]
1460impl usize {
1461 uint_impl! {
1462 Self = usize,
1463 ActualT = u64,
1464 SignedT = isize,
1465 BITS = 64,
1466 BITS_MINUS_ONE = 63,
1467 MAX = 18446744073709551615,
1468 rot = 12,
1469 rot_op = "0x0aa00000000006e1",
1470 rot_result = "0x00000000006e10aa",
1471 fsh_op = "0x2fe78e45983acd98",
1472 fshl_result = "0x00000000006e12fe",
1473 fshr_result = "0x6e12fe78e45983ac",
1474 clmul_lhs = "0x7890123456789012",
1475 clmul_rhs = "0xdd358416f52ecd34",
1476 clmul_result = "0xa6299579b980928",
1477 swap_op = "0x1234567890123456",
1478 swapped = "0x5634129078563412",
1479 reversed = "0x6a2c48091e6a2c48",
1480 le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
1481 be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
1482 to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
1483 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
1484 bound_condition = " on 64-bit targets",
1485 }
1486 midpoint_impl! { usize, u128, unsigned }
1487 carrying_carryless_mul_impl! { usize, u128 }
1488}
1489
1490impl usize {
1491 /// Returns an `usize` where every byte is equal to `x`.
1492 #[inline]
1493 pub(crate) const fn repeat_u8(x: u8) -> usize {
1494 usize::from_ne_bytes([x; size_of::<usize>()])
1495 }
1496
1497 /// Returns an `usize` where every byte pair is equal to `x`.
1498 #[inline]
1499 pub(crate) const fn repeat_u16(x: u16) -> usize {
1500 let mut r = 0usize;
1501 let mut i = 0;
1502 while i < size_of::<usize>() {
1503 // Use `wrapping_shl` to make it work on targets with 16-bit `usize`
1504 r = r.wrapping_shl(16) | (x as usize);
1505 i += 2;
1506 }
1507 r
1508 }
1509}
1510
1511/// A classification of floating point numbers.
1512///
1513/// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See
1514/// their documentation for more.
1515///
1516/// # Examples
1517///
1518/// ```
1519/// use std::num::FpCategory;
1520///
1521/// let num = 12.4_f32;
1522/// let inf = f32::INFINITY;
1523/// let zero = 0f32;
1524/// let sub: f32 = 1.1754942e-38;
1525/// let nan = f32::NAN;
1526///
1527/// assert_eq!(num.classify(), FpCategory::Normal);
1528/// assert_eq!(inf.classify(), FpCategory::Infinite);
1529/// assert_eq!(zero.classify(), FpCategory::Zero);
1530/// assert_eq!(sub.classify(), FpCategory::Subnormal);
1531/// assert_eq!(nan.classify(), FpCategory::Nan);
1532/// ```
1533#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1534#[stable(feature = "rust1", since = "1.0.0")]
1535pub enum FpCategory {
1536 /// NaN (not a number): this value results from calculations like `(-1.0).sqrt()`.
1537 ///
1538 /// See [the documentation for `f32`](f32) for more information on the unusual properties
1539 /// of NaN.
1540 #[stable(feature = "rust1", since = "1.0.0")]
1541 Nan,
1542
1543 /// Positive or negative infinity, which often results from dividing a nonzero number
1544 /// by zero.
1545 #[stable(feature = "rust1", since = "1.0.0")]
1546 Infinite,
1547
1548 /// Positive or negative zero.
1549 ///
1550 /// See [the documentation for `f32`](f32) for more information on the signedness of zeroes.
1551 #[stable(feature = "rust1", since = "1.0.0")]
1552 Zero,
1553
1554 /// “Subnormal” or “denormal” floating point representation (less precise, relative to
1555 /// their magnitude, than [`Normal`]).
1556 ///
1557 /// Subnormal numbers are larger in magnitude than [`Zero`] but smaller in magnitude than all
1558 /// [`Normal`] numbers.
1559 ///
1560 /// [`Normal`]: Self::Normal
1561 /// [`Zero`]: Self::Zero
1562 #[stable(feature = "rust1", since = "1.0.0")]
1563 Subnormal,
1564
1565 /// A regular floating point number, not any of the exceptional categories.
1566 ///
1567 /// The smallest positive normal numbers are [`f32::MIN_POSITIVE`] and [`f64::MIN_POSITIVE`],
1568 /// and the largest positive normal numbers are [`f32::MAX`] and [`f64::MAX`]. (Unlike signed
1569 /// integers, floating point numbers are symmetric in their range, so negating any of these
1570 /// constants will produce their negative counterpart.)
1571 #[stable(feature = "rust1", since = "1.0.0")]
1572 Normal,
1573}
1574
1575/// Determines if a string of text of that length of that radix could be guaranteed to be
1576/// stored in the given type T.
1577/// Note that if the radix is known to the compiler, it is just the check of digits.len that
1578/// is done at runtime.
1579#[doc(hidden)]
1580#[inline(always)]
1581#[unstable(issue = "none", feature = "std_internals")]
1582pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool {
1583 // Assume that `digits` represents a whole number N in base `radix`.
1584 // Then in infinite precision arithmetic (on whole numbers), we have:
1585 //
1586 // |N| <= pow(radix, digits.len()) - 1
1587 // <= pow(16, 2 * size_of::<T>() - is_signed) - 1
1588 // == pow(2, 8 * size_of::<T>() - 4 * is_signed) - 1
1589 // <= pow(2, 8 * size_of::<T>() - is_signed) - 1
1590 // == T::MAX
1591 //
1592 // Therefore this condition is sufficient for having no overflow.
1593 radix <= 16 && digits.len() <= size_of::<T>() * 2 - is_signed_ty as usize
1594}
1595
1596#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
1597#[cfg_attr(panic = "immediate-abort", inline)]
1598#[cold]
1599#[track_caller]
1600const fn from_ascii_bytes_radix_panic(radix: u32) -> ! {
1601 const_panic!(
1602 "from_ascii_bytes_radix: radix must lie in the range `[2, 36]`",
1603 "from_ascii_bytes_radix: radix must lie in the range `[2, 36]` - found {radix}",
1604 radix: u32 = radix,
1605 )
1606}
1607
1608macro_rules! from_str_int_impl {
1609 ($signedness:ident $($int_ty:ty)+) => {$(
1610 #[stable(feature = "rust1", since = "1.0.0")]
1611 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1612 const impl FromStr for $int_ty {
1613 type Err = ParseIntError;
1614
1615 /// Parses an integer from a string slice with decimal digits.
1616 ///
1617 /// The characters are expected to be an optional
1618 #[doc = sign_dependent_expr!{
1619 $signedness ?
1620 if signed {
1621 " `+` or `-` "
1622 }
1623 if unsigned {
1624 " `+` "
1625 }
1626 }]
1627 /// sign followed by only digits. Leading and trailing non-digit characters (including
1628 /// whitespace) represent an error. Underscores (which are accepted in Rust literals)
1629 /// also represent an error.
1630 ///
1631 /// # See also
1632 /// For parsing numbers in other bases, such as binary or hexadecimal,
1633 /// see [`from_str_radix`][Self::from_str_radix].
1634 ///
1635 /// # Examples
1636 ///
1637 /// ```
1638 /// use std::str::FromStr;
1639 ///
1640 #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str(\"+10\"), Ok(10));")]
1641 /// ```
1642 /// Trailing space returns error:
1643 /// ```
1644 /// # use std::str::FromStr;
1645 /// #
1646 #[doc = concat!("assert!(", stringify!($int_ty), "::from_str(\"1 \").is_err());")]
1647 /// ```
1648 #[inline]
1649 fn from_str(src: &str) -> Result<$int_ty, ParseIntError> {
1650 <$int_ty>::from_str_radix(src, 10)
1651 }
1652 }
1653
1654 impl $int_ty {
1655 /// Parses an integer from a string slice with digits in a given base.
1656 ///
1657 /// The string is expected to be an optional
1658 #[doc = sign_dependent_expr!{
1659 $signedness ?
1660 if signed {
1661 " `+` or `-` "
1662 }
1663 if unsigned {
1664 " `+` "
1665 }
1666 }]
1667 /// sign followed by only digits. Leading and trailing non-digit characters (including
1668 /// whitespace) represent an error. Underscores (which are accepted in Rust literals)
1669 /// also represent an error.
1670 ///
1671 /// Digits are a subset of these characters, depending on `radix`:
1672 /// * `0-9`
1673 /// * `a-z`
1674 /// * `A-Z`
1675 ///
1676 /// # Panics
1677 ///
1678 /// This function panics if `radix` is not in the range from 2 to 36.
1679 ///
1680 /// # See also
1681 /// If the string to be parsed is in base 10 (decimal),
1682 /// [`from_str`] or [`str::parse`] can also be used.
1683 ///
1684 // FIXME(#122566): These HTML links work around a rustdoc-json test failure.
1685 /// [`from_str`]: #method.from_str
1686 /// [`str::parse`]: primitive.str.html#method.parse
1687 ///
1688 /// # Examples
1689 ///
1690 /// ```
1691 #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")]
1692 /// ```
1693 /// Trailing space returns error:
1694 /// ```
1695 #[doc = concat!("assert!(", stringify!($int_ty), "::from_str_radix(\"1 \", 10).is_err());")]
1696 /// ```
1697 #[stable(feature = "rust1", since = "1.0.0")]
1698 #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
1699 #[inline]
1700 pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> {
1701 <$int_ty>::from_ascii_bytes_radix_impl(src.as_bytes(), radix)
1702 }
1703
1704 /// Parses an integer from an ASCII-byte slice with decimal digits.
1705 ///
1706 /// The characters are expected to be an optional
1707 #[doc = sign_dependent_expr!{
1708 $signedness ?
1709 if signed {
1710 " `+` or `-` "
1711 }
1712 if unsigned {
1713 " `+` "
1714 }
1715 }]
1716 /// sign followed by only digits. Leading and trailing non-digit characters (including
1717 /// whitespace) represent an error. Underscores (which are accepted in Rust literals)
1718 /// also represent an error.
1719 ///
1720 /// # Examples
1721 ///
1722 /// ```
1723 /// #![feature(int_from_ascii)]
1724 ///
1725 #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_ascii_bytes(b\"+10\"), Ok(10));")]
1726 /// ```
1727 /// Trailing space returns error:
1728 /// ```
1729 /// # #![feature(int_from_ascii)]
1730 /// #
1731 #[doc = concat!("assert!(", stringify!($int_ty), "::from_ascii_bytes(b\"1 \").is_err());")]
1732 /// ```
1733 #[unstable(feature = "int_from_ascii", issue = "134821")]
1734 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1735 #[inline]
1736 pub const fn from_ascii_bytes<T>(src: T) -> Result<$int_ty, ParseIntError>
1737 where
1738 T: [const] AsRef<[u8]> + [const] crate::marker::Destruct
1739 {
1740 <$int_ty>::from_ascii_bytes_radix(src.as_ref(), 10)
1741 }
1742
1743 /// Parses an integer from an ASCII-byte slice with digits in a given base.
1744 ///
1745 /// The characters are expected to be an optional
1746 #[doc = sign_dependent_expr!{
1747 $signedness ?
1748 if signed {
1749 " `+` or `-` "
1750 }
1751 if unsigned {
1752 " `+` "
1753 }
1754 }]
1755 /// sign followed by only digits. Leading and trailing non-digit characters (including
1756 /// whitespace) represent an error. Underscores (which are accepted in Rust literals)
1757 /// also represent an error.
1758 ///
1759 /// Digits are a subset of these characters, depending on `radix`:
1760 /// * `0-9`
1761 /// * `a-z`
1762 /// * `A-Z`
1763 ///
1764 /// # Panics
1765 ///
1766 /// This function panics if `radix` is not in the range from 2 to 36.
1767 ///
1768 /// # Examples
1769 ///
1770 /// ```
1771 /// #![feature(int_from_ascii)]
1772 ///
1773 #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_ascii_bytes_radix(b\"A\", 16), Ok(10));")]
1774 /// ```
1775 /// Trailing space returns error:
1776 /// ```
1777 /// # #![feature(int_from_ascii)]
1778 /// #
1779 #[doc = concat!("assert!(", stringify!($int_ty), "::from_ascii_bytes_radix(b\"1 \", 10).is_err());")]
1780 /// ```
1781 #[unstable(feature = "int_from_ascii", issue = "134821")]
1782 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1783 #[inline]
1784 pub const fn from_ascii_bytes_radix<T>(src: T, radix: u32) -> Result<$int_ty, ParseIntError>
1785 where
1786 T: [const] AsRef<[u8]> + [const] crate::marker::Destruct
1787 {
1788 <$int_ty>::from_ascii_bytes_radix_impl(src.as_ref(), radix)
1789 }
1790
1791 #[inline]
1792 pub(super) const fn from_ascii_bytes_radix_impl(src: &[u8], radix: u32) -> Result<$int_ty, ParseIntError> {
1793 use self::IntErrorKind::*;
1794 use self::ParseIntError as PIE;
1795
1796 if 2 > radix || radix > 36 {
1797 from_ascii_bytes_radix_panic(radix);
1798 }
1799
1800 if src.is_empty() {
1801 return Err(PIE { kind: Empty });
1802 }
1803
1804 #[allow(unused_comparisons)]
1805 let is_signed_ty = 0 > <$int_ty>::MIN;
1806
1807 let (is_positive, mut digits) = match src {
1808 [b'+' | b'-'] => {
1809 return Err(PIE { kind: InvalidDigit });
1810 }
1811 [b'+', rest @ ..] => (true, rest),
1812 [b'-', rest @ ..] if is_signed_ty => (false, rest),
1813 _ => (true, src),
1814 };
1815
1816 let mut result = 0;
1817
1818 macro_rules! unwrap_or_PIE {
1819 ($option:expr, $kind:ident) => {
1820 match $option {
1821 Some(value) => value,
1822 None => return Err(PIE { kind: $kind }),
1823 }
1824 };
1825 }
1826
1827 if can_not_overflow::<$int_ty>(radix, is_signed_ty, digits) {
1828 // If the len of the str is short compared to the range of the type
1829 // we are parsing into, then we can be certain that an overflow will not occur.
1830 // This bound is when `radix.pow(digits.len()) - 1 <= T::MAX` but the condition
1831 // above is a faster (conservative) approximation of this.
1832 //
1833 // Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest:
1834 // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow.
1835 // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow.
1836 //
1837 // NOTE: We could use unchecked arithmetic here, but we don't, based on the observation
1838 // that it produces the same assembly as wrapping ones. See #163099.
1839 macro_rules! run_no_check_loop {
1840 ($additive_op:ident) => {{
1841 while let [c, rest @ ..] = digits {
1842 result = <$int_ty>::wrapping_mul(result, radix as _);
1843 let x = unwrap_or_PIE!((*c as char).to_digit(radix), InvalidDigit);
1844 result = result.$additive_op(x as $int_ty);
1845 digits = rest;
1846 }
1847 }};
1848 }
1849 if is_positive {
1850 run_no_check_loop!(wrapping_add)
1851 } else {
1852 run_no_check_loop!(wrapping_sub)
1853 };
1854 } else {
1855 macro_rules! run_checked_loop {
1856 ($checked_additive_op:ident, $overflow_err:ident) => {{
1857 while let [c, rest @ ..] = digits {
1858 // When `radix` is passed in as a literal, rather than doing a slow `imul`
1859 // the compiler can use shifts if `radix` can be expressed as a
1860 // sum of powers of 2 (x*10 can be written as x*8 + x*2).
1861 // When the compiler can't use these optimisations,
1862 // the latency of the multiplication can be hidden by issuing it
1863 // before the result is needed to improve performance on
1864 // modern out-of-order CPU as multiplication here is slower
1865 // than the other instructions, we can get the end result faster
1866 // doing multiplication first and let the CPU spends other cycles
1867 // doing other computation and get multiplication result later.
1868 let mul = result.checked_mul(radix as $int_ty);
1869 let x = unwrap_or_PIE!((*c as char).to_digit(radix), InvalidDigit) as $int_ty;
1870 result = unwrap_or_PIE!(mul, $overflow_err);
1871 result = unwrap_or_PIE!(<$int_ty>::$checked_additive_op(result, x), $overflow_err);
1872 digits = rest;
1873 }
1874 }};
1875 }
1876 if is_positive {
1877 run_checked_loop!(checked_add, PosOverflow)
1878 } else {
1879 run_checked_loop!(checked_sub, NegOverflow)
1880 };
1881 }
1882 Ok(result)
1883 }
1884 }
1885 )*}
1886}
1887
1888from_str_int_impl! { signed isize i8 i16 i32 i64 i128 }
1889from_str_int_impl! { unsigned usize u8 u16 u32 u64 u128 }