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