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