diff --git a/library/core/benches/ascii/is_ascii.rs b/library/core/benches/ascii/is_ascii.rs index 729b0a04eb6ba..a42a1dcfe3988 100644 --- a/library/core/benches/ascii/is_ascii.rs +++ b/library/core/benches/ascii/is_ascii.rs @@ -77,6 +77,6 @@ fn is_ascii_align_to_unrolled(bytes: &[u8]) -> bool { #[inline] fn contains_nonascii(v: usize) -> bool { - const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; + const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; core::mem::size_of::()]); (NONASCII_MASK & v) != 0 } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 8b93cd39d5df3..66193eaf5da73 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -890,6 +890,27 @@ impl usize { widening_impl! { usize, u128, 64, unsigned } } +impl usize { + /// Returns an `usize` where every byte is equal to `x`. + #[inline] + pub(crate) const fn repeat_u8(x: u8) -> usize { + usize::from_ne_bytes([x; mem::size_of::()]) + } + + /// Returns an `usize` where every byte pair is equal to `x`. + #[inline] + pub(crate) const fn repeat_u16(x: u16) -> usize { + let mut r = 0usize; + let mut i = 0; + while i < mem::size_of::() { + // Use `wrapping_shl` to make it work on targets with 16-bit `usize` + r = r.wrapping_shl(16) | (x as usize); + i += 2; + } + r + } +} + /// A classification of floating point numbers. /// /// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 9aa5c88a62c8e..63715a6b86b97 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -235,7 +235,7 @@ impl<'a> fmt::Debug for EscapeAscii<'a> { /// from `../str/mod.rs`, which does something similar for utf8 validation. #[inline] fn contains_nonascii(v: usize) -> bool { - const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; + const NONASCII_MASK: usize = usize::repeat_u8(0x80); (NONASCII_MASK & v) != 0 } diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 6da99055f2d5a..dffeaf6a834e7 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -4,12 +4,8 @@ use crate::cmp; use crate::mem; -const LO_U64: u64 = 0x0101010101010101; -const HI_U64: u64 = 0x8080808080808080; - -// Use truncation. -const LO_USIZE: usize = LO_U64 as usize; -const HI_USIZE: usize = HI_U64 as usize; +const LO_USIZE: usize = usize::repeat_u8(0x01); +const HI_USIZE: usize = usize::repeat_u8(0x80); const USIZE_BYTES: usize = mem::size_of::(); /// Returns `true` if `x` contains any zero byte. diff --git a/library/core/src/str/count.rs b/library/core/src/str/count.rs index 5abc2b34c075a..28567a7e753aa 100644 --- a/library/core/src/str/count.rs +++ b/library/core/src/str/count.rs @@ -112,7 +112,7 @@ fn do_count_chars(s: &str) -> usize { // true) #[inline] fn contains_non_continuation_byte(w: usize) -> usize { - const LSB: usize = 0x0101_0101_0101_0101u64 as usize; + const LSB: usize = usize::repeat_u8(0x01); ((!w >> 7) | (w >> 6)) & LSB } @@ -120,8 +120,8 @@ fn contains_non_continuation_byte(w: usize) -> usize { // more efficient. #[inline] fn sum_bytes_in_usize(values: usize) -> usize { - const LSB_SHORTS: usize = 0x0001_0001_0001_0001_u64 as usize; - const SKIP_BYTES: usize = 0x00ff_00ff_00ff_00ff_u64 as usize; + const LSB_SHORTS: usize = usize::repeat_u16(0x0001); + const SKIP_BYTES: usize = usize::repeat_u16(0x00ff); let pair_sum: usize = (values & SKIP_BYTES) + ((values >> 8) & SKIP_BYTES); pair_sum.wrapping_mul(LSB_SHORTS) >> ((USIZE_SIZE - 2) * 8) diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs index 0d3dc856be577..04bc665233e38 100644 --- a/library/core/src/str/validations.rs +++ b/library/core/src/str/validations.rs @@ -112,8 +112,7 @@ where Some(ch) } -// use truncation to fit u64 into usize -const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; +const NONASCII_MASK: usize = usize::repeat_u8(0x80); /// Returns `true` if any byte in the word `x` is nonascii (>= 128). #[inline]