From e1c7a1ed77bc1025d938c47b6307f43133469111 Mon Sep 17 00:00:00 2001 From: may <63159454+m4rch3n1ng@users.noreply.github.com> Date: Thu, 27 Feb 2025 02:03:29 +0100 Subject: [PATCH] remove unnecessary allocations in switch_case (#12786) --- helix-term/src/commands.rs | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index a95e2a90..6c221ed3 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -67,6 +67,7 @@ use crate::{ use crate::job::{self, Jobs}; use std::{ + char::{ToLowercase, ToUppercase}, cmp::Ordering, collections::{HashMap, HashSet}, error::Error, @@ -1727,17 +1728,48 @@ 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 .chars() .flat_map(|ch| { if ch.is_lowercase() { - ch.to_uppercase().collect() + CaseSwitcher::Upper(ch.to_uppercase()) } else if ch.is_uppercase() { - ch.to_lowercase().collect() + CaseSwitcher::Lower(ch.to_lowercase()) } else { - vec![ch] + CaseSwitcher::Keep(Some(ch)) } }) .collect()