Skip to content

Commit

Permalink
Make {str,[u8]}::eq_ignore_ascii_case const
Browse files Browse the repository at this point in the history
  • Loading branch information
coolreader18 committed May 10, 2023
1 parent cba1407 commit fd78ba1
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 4 deletions.
2 changes: 1 addition & 1 deletion library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2449,7 +2449,7 @@ extern "rust-intrinsic" {
/// const fn compiletime() -> i32 { 2 }
///
/// unsafe {
// // ⚠ This code violates the required equivalence of `compiletime`
/// // ⚠ This code violates the required equivalence of `compiletime`
/// // and `runtime`.
/// const_eval_select((), compiletime, runtime)
/// }
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
#![feature(const_replace)]
#![feature(const_size_of_val)]
#![feature(const_size_of_val_raw)]
#![feature(const_slice_eq_ignore_ascii_case)]
#![feature(const_slice_from_raw_parts_mut)]
#![feature(const_slice_from_ref)]
#![feature(const_slice_index)]
Expand Down
28 changes: 26 additions & 2 deletions library/core/src/slice/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::ascii;
use crate::fmt::{self, Write};
use crate::intrinsics;
use crate::iter;
use crate::mem;
use crate::ops;
Expand Down Expand Up @@ -52,10 +53,33 @@ impl [u8] {
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
/// but without allocating and copying temporaries.
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[rustc_const_unstable(feature = "const_slice_eq_ignore_ascii_case", issue = "none")]
#[must_use]
#[inline]
pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b))
pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
const fn eq_ignore_ascii_case_ct(a: &[u8], b: &[u8]) -> bool {
a.len() == b.len() && {
let mut i = 0;
while i < a.len() {
if !u8::eq_ignore_ascii_case(&a[i], &b[i]) {
return false;
}
i += 1;
}
true
}
}
fn eq_ignore_ascii_case_rt(a: &[u8], b: &[u8]) -> bool {
a.len() == b.len() && iter::zip(a, b).all(|(a, b)| u8::eq_ignore_ascii_case(a, b))
}
// SAFETY: both branches compute the same result, the runtime one is just more optimized
unsafe {
intrinsics::const_eval_select(
(self, other),
eq_ignore_ascii_case_ct,
eq_ignore_ascii_case_rt,
)
}
}

/// Converts this slice to its ASCII upper case equivalent in-place.
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2391,9 +2391,10 @@ impl str {
/// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[rustc_const_unstable(feature = "const_slice_eq_ignore_ascii_case", issue = "none")]
#[must_use]
#[inline]
pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool {
self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
}

Expand Down
26 changes: 26 additions & 0 deletions library/core/tests/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ fn test_is_ascii() {
assert!(!"ประเทศไทย中华ệ ".chars().any(|c| c.is_ascii()));
}

#[test]
fn test_is_ascii_const() {
const _: () = {
assert!(b"".is_ascii());
assert!(b"banana\0\x7F".is_ascii());
assert!(!b"Vi\xe1\xbb\x87t Nam".is_ascii());

assert!("".is_ascii());
assert!("banana\0\u{7F}".is_ascii());
assert!(!"ประเทศไทย中华Việt Nam".is_ascii());
};
}

#[test]
fn test_to_ascii_uppercase() {
assert_eq!("url()URL()uRl()ürl".to_ascii_uppercase(), "URL()URL()URL()üRL");
Expand Down Expand Up @@ -112,6 +125,19 @@ fn test_eq_ignore_ascii_case() {
}
}

#[test]
fn test_eq_ignore_ascii_case_const() {
const _: () = {
assert!("url()URL()uRl()Ürl".eq_ignore_ascii_case("url()url()url()Ürl"));
assert!(!"Ürl".eq_ignore_ascii_case("ürl"));
// Dotted capital I, Kelvin sign, Sharp S.
assert!("HİKß".eq_ignore_ascii_case("hİKß"));
assert!(!"İ".eq_ignore_ascii_case("i"));
assert!(!"K".eq_ignore_ascii_case("k"));
assert!(!"ß".eq_ignore_ascii_case("s"));
};
}

#[test]
fn inference_works() {
let x = "a".to_string();
Expand Down
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#![feature(const_pointer_is_aligned)]
#![feature(const_ptr_as_ref)]
#![feature(const_ptr_write)]
#![feature(const_slice_eq_ignore_ascii_case)]
#![feature(const_trait_impl)]
#![feature(const_likely)]
#![feature(const_location_fields)]
Expand Down

0 comments on commit fd78ba1

Please sign in to comment.