From 917e8057dc60d6bd80b6e6bf2ee3db235885e29a Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Fri, 28 Feb 2025 15:16:25 +0000 Subject: [PATCH] fix: remove extra allocs from alternate case impl --- helix-core/src/case_conversion.rs | 57 +++++++++++++++++++++++++------ helix-term/src/commands.rs | 31 ----------------- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/helix-core/src/case_conversion.rs b/helix-core/src/case_conversion.rs index 0bd0053cc..f0268eed7 100644 --- a/helix-core/src/case_conversion.rs +++ b/helix-core/src/case_conversion.rs @@ -1,3 +1,5 @@ +use std::char::{ToLowercase, ToUppercase}; + use crate::Tendril; // todo: should this be grapheme aware? @@ -87,24 +89,57 @@ pub fn separator_case_conversion( } } -pub fn into_alternate_case(chars: impl Iterator, buf: &mut Tendril) { - simple_case_conversion(chars, buf, |ch| { - if ch.is_uppercase() { - ch.to_ascii_lowercase() - } else if ch.is_lowercase() { - ch.to_ascii_uppercase() - } else { - *ch +enum AlternateCase { + Upper(ToUppercase), + Lower(ToLowercase), + Keep(Option), +} + +impl Iterator for AlternateCase { + type Item = char; + + fn next(&mut self) -> Option { + match self { + AlternateCase::Upper(upper) => upper.next(), + AlternateCase::Lower(lower) => lower.next(), + AlternateCase::Keep(ch) => ch.take(), } - }); + } + + fn size_hint(&self) -> (usize, Option) { + 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, 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, 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, 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, buf: &mut Tendril) { diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 7ccb63f27..adf7b4555 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -1739,37 +1739,6 @@ where exit_select_mode(cx); } -enum CaseSwitcher { - Upper(ToUppercase), - Lower(ToLowercase), - Keep(Option), -} - -impl Iterator for CaseSwitcher { - type Item = char; - - fn next(&mut self) -> Option { - match self { - CaseSwitcher::Upper(upper) => upper.next(), - CaseSwitcher::Lower(lower) => lower.next(), - CaseSwitcher::Keep(ch) => ch.take(), - } - } - - fn size_hint(&self) -> (usize, Option) { - 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) { switch_case_impl(cx, |string| { string