fix: remove extra allocs from alternate case impl

pull/12043/head
Nikita Revenco 2025-02-28 15:16:25 +00:00
parent c7cbb4e0c9
commit 917e8057dc
2 changed files with 46 additions and 42 deletions

View File

@ -1,3 +1,5 @@
use std::char::{ToLowercase, ToUppercase};
use crate::Tendril; use crate::Tendril;
// todo: should this be grapheme aware? // todo: should this be grapheme aware?
@ -87,24 +89,57 @@ pub fn separator_case_conversion(
} }
} }
pub fn into_alternate_case(chars: impl Iterator<Item = char>, buf: &mut Tendril) { enum AlternateCase {
simple_case_conversion(chars, buf, |ch| { Upper(ToUppercase),
if ch.is_uppercase() { Lower(ToLowercase),
ch.to_ascii_lowercase() Keep(Option<char>),
} else if ch.is_lowercase() { }
ch.to_ascii_uppercase()
} else { impl Iterator for AlternateCase {
*ch type Item = char;
fn next(&mut self) -> Option<Self::Item> {
match self {
AlternateCase::Upper(upper) => upper.next(),
AlternateCase::Lower(lower) => lower.next(),
AlternateCase::Keep(ch) => ch.take(),
} }
}); }
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
AlternateCase::Upper(upper) => upper.size_hint(),
AlternateCase::Lower(lower) => lower.size_hint(),
AlternateCase::Keep(ch) => {
let n = if ch.is_some() { 1 } else { 0 };
(n, Some(n))
}
}
}
}
impl ExactSizeIterator for AlternateCase {}
pub fn into_alternate_case(chars: impl Iterator<Item = char>, buf: &mut Tendril) {
*buf = chars
.flat_map(|ch| {
if ch.is_lowercase() {
AlternateCase::Upper(ch.to_uppercase())
} else if ch.is_uppercase() {
AlternateCase::Lower(ch.to_lowercase())
} else {
AlternateCase::Keep(Some(ch))
}
})
.collect();
} }
pub fn into_uppercase(chars: impl Iterator<Item = char>, buf: &mut Tendril) { pub fn into_uppercase(chars: impl Iterator<Item = char>, buf: &mut Tendril) {
simple_case_conversion(chars, buf, char::to_ascii_uppercase); *buf = chars.map(|ch| char::to_ascii_uppercase(&ch)).collect();
} }
pub fn into_lowercase(chars: impl Iterator<Item = char>, buf: &mut Tendril) { pub fn into_lowercase(chars: impl Iterator<Item = char>, buf: &mut Tendril) {
simple_case_conversion(chars, buf, char::to_ascii_lowercase); *buf = chars.map(|ch| char::to_ascii_lowercase(&ch)).collect();
} }
pub fn into_kebab_case(chars: impl Iterator<Item = char>, buf: &mut Tendril) { pub fn into_kebab_case(chars: impl Iterator<Item = char>, buf: &mut Tendril) {

View File

@ -1739,37 +1739,6 @@ where
exit_select_mode(cx); exit_select_mode(cx);
} }
enum CaseSwitcher {
Upper(ToUppercase),
Lower(ToLowercase),
Keep(Option<char>),
}
impl Iterator for CaseSwitcher {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
match self {
CaseSwitcher::Upper(upper) => upper.next(),
CaseSwitcher::Lower(lower) => lower.next(),
CaseSwitcher::Keep(ch) => ch.take(),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
CaseSwitcher::Upper(upper) => upper.size_hint(),
CaseSwitcher::Lower(lower) => lower.size_hint(),
CaseSwitcher::Keep(ch) => {
let n = if ch.is_some() { 1 } else { 0 };
(n, Some(n))
}
}
}
}
impl ExactSizeIterator for CaseSwitcher {}
fn switch_case(cx: &mut Context) { fn switch_case(cx: &mut Context) {
switch_case_impl(cx, |string| { switch_case_impl(cx, |string| {
string string