mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Use icu4x for casefold() (#7780)
This commit is contained in:
1 parent
acf12468c4
commit
41e4b4c637
4 files changed
+24
-25
No files matched your search
Generated
-10
@@ -429,15 +429,6 @@ dependencies = [
|
||||
"libbz2-rs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "caseless"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8"
|
||||
dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
@@ -3561,7 +3552,6 @@ dependencies = [
|
||||
"ascii",
|
||||
"bitflags 2.11.0",
|
||||
"bstr",
|
||||
"caseless",
|
||||
"chrono",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
|
||||
@@ -186,7 +186,6 @@ bitflags = "2.11.0"
|
||||
bitflagset = "0.0.3"
|
||||
bstr = "1"
|
||||
bzip2 = "0.6"
|
||||
caseless = "0.2.2"
|
||||
chrono = { version = "0.4.44", default-features = false, features = ["clock", "std"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
constant_time_eq = "0.4"
|
||||
|
||||
@@ -73,7 +73,6 @@ strum_macros = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
memchr = { workspace = true }
|
||||
|
||||
caseless = { workspace = true }
|
||||
flamer = { workspace = true, optional = true }
|
||||
half = { workspace = true }
|
||||
psm = { workspace = true }
|
||||
|
||||
@@ -45,10 +45,10 @@ use rustpython_common::{
|
||||
hash,
|
||||
lock::PyMutex,
|
||||
str::DeduceStrKind,
|
||||
wtf8::{CodePoint, Wtf8, Wtf8Buf, Wtf8Chunk, Wtf8Concat},
|
||||
wtf8::{CodePoint, Wtf8, Wtf8Buf, Wtf8Concat},
|
||||
};
|
||||
|
||||
use icu_casemap::TitlecaseMapper;
|
||||
use icu_casemap::{CaseMapper, TitlecaseMapper};
|
||||
use icu_locale::LanguageIdentifier;
|
||||
use icu_properties::props::{
|
||||
BidiClass, BinaryProperty, CaseIgnorable, Cased, EnumeratedProperty, GeneralCategory,
|
||||
@@ -743,20 +743,31 @@ impl PyStr {
|
||||
}
|
||||
}
|
||||
|
||||
// casefold is much more aggressive than lower
|
||||
// Case folding is a Unicode standard operation to erase case differences.
|
||||
//
|
||||
// Lower, upper, and title case are special properties. Case folding erases those
|
||||
// differences. For ASCII, case folding is the same as lower case but other scripts have
|
||||
// their own, well-defined mappings.
|
||||
#[pymethod]
|
||||
fn casefold(&self) -> Self {
|
||||
match self.as_str_kind() {
|
||||
PyKindStr::Ascii(s) => caseless::default_case_fold_str(s.as_str()).into(),
|
||||
PyKindStr::Utf8(s) => caseless::default_case_fold_str(s).into(),
|
||||
PyKindStr::Wtf8(w) => w
|
||||
.chunks()
|
||||
.map(|c| match c {
|
||||
Wtf8Chunk::Utf8(s) => Wtf8Buf::from_string(caseless::default_case_fold_str(s)),
|
||||
Wtf8Chunk::Surrogate(c) => Wtf8Buf::from(c),
|
||||
})
|
||||
.collect::<Wtf8Buf>()
|
||||
.into(),
|
||||
PyKindStr::Ascii(s) => s.to_ascii_lowercase().into(),
|
||||
PyKindStr::Utf8(s) => CaseMapper::new().fold_string(s).to_string().into(),
|
||||
PyKindStr::Wtf8(w) => {
|
||||
let mut out = VecFmtWriter(Vec::with_capacity(w.len()));
|
||||
let mapper = CaseMapper::new();
|
||||
for chunk in w.as_bytes().utf8_chunks() {
|
||||
mapper
|
||||
.fold(chunk.valid())
|
||||
.write_to(&mut out)
|
||||
.expect("Writing to an in-memory buffer cannot fail.");
|
||||
out.0.extend(chunk.invalid());
|
||||
}
|
||||
// SAFETY:
|
||||
// * CaseMapper only produces valid UTF-8
|
||||
// * Surrogates are appended as-is
|
||||
unsafe { Wtf8Buf::from_bytes_unchecked(out.0) }.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user