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