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