perf: avoid unnecessary memory allocation in ya.truncate() (#2753)

This commit is contained in:
三咲雅 · Misaki Masa 2025-05-14 01:34:16 +08:00 committed by GitHub
parent 55f69fbfee
commit cea2628a19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 26 deletions

8
Cargo.lock generated
View file

@ -385,9 +385,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.37"
version = "4.5.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000"
dependencies = [
"clap_builder",
"clap_derive",
@ -395,9 +395,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.37"
version = "4.5.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120"
dependencies = [
"anstream",
"anstyle",

View file

@ -24,7 +24,7 @@ ansi-to-tui = "7.0.0"
anyhow = "1.0.98"
base64 = "0.22.1"
bitflags = "2.9.0"
clap = { version = "4.5.37", features = [ "derive" ] }
clap = { version = "4.5.38", features = [ "derive" ] }
core-foundation-sys = "0.8.7"
crossterm = { version = "0.29.0", features = [ "event-stream" ] }
dirs = "6.0.0"
@ -50,5 +50,5 @@ tokio-util = "0.7.15"
toml = { version = "0.8.22" }
tracing = { version = "0.1.41", features = [ "max_level_debug", "release_max_level_debug" ] }
twox-hash = { version = "2.1.0", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
unicode-width = "0.2.0"
unicode-width = { version = "0.2.0", default-features = false }
uzers = "0.12.1"

View file

@ -167,7 +167,7 @@ impl Cha {
#[inline]
pub const fn is_hidden(&self) -> bool {
self.kind.contains(ChaKind::HIDDEN) || win_either!(self.kind.contains(ChaKind::SYSTEM), false)
win_either!(self.kind.contains(ChaKind::SYSTEM), self.kind.contains(ChaKind::HIDDEN))
}
#[inline]

View file

@ -1,4 +1,3 @@
use std::ops::ControlFlow;
use mlua::{Function, Lua, Table};
use twox_hash::XxHash3_128;
use unicode_width::UnicodeWidthChar;
@ -26,32 +25,55 @@ impl Utils {
}
pub(super) fn truncate(lua: &Lua) -> mlua::Result<Function> {
fn truncate_impl(mut chars: impl Iterator<Item = char>, max: usize) -> Vec<char> {
fn idx_and_width(it: impl Iterator<Item = (usize, char)>, max: usize) -> (usize, usize) {
let mut width = 0;
let flow = chars.try_fold(Vec::with_capacity(max), |mut v, c| {
let idx = it
.take_while(|(_, c)| {
width += c.width().unwrap_or(0);
if width < max {
v.push(c);
ControlFlow::Continue(v)
} else {
ControlFlow::Break(v)
width <= max
})
.map(|(i, _)| i)
.last()
.unwrap();
(idx, width)
}
});
match flow {
ControlFlow::Break(v) => v,
ControlFlow::Continue(v) => v,
}
lua.create_function(|lua, (s, t): (mlua::String, Table)| {
let b = s.as_bytes();
if b.is_empty() {
return Ok(s);
}
lua.create_function(|_, (text, t): (mlua::String, Table)| {
let (max, text) = (t.raw_get("max")?, text.to_string_lossy());
let max = t.raw_get("max")?;
if b.len() <= max {
return Ok(s);
} else if max < 1 {
return lua.create_string("");
}
Ok(if t.raw_get("rtl").unwrap_or(false) {
truncate_impl(text.chars().rev(), max).into_iter().rev().collect()
let lossy = String::from_utf8_lossy(&b);
let rtl = t.raw_get("rtl").unwrap_or(false);
let (idx, width) = if rtl {
idx_and_width(lossy.char_indices().rev(), max)
} else {
truncate_impl(text.chars(), max).into_iter().collect::<String>()
})
idx_and_width(lossy.char_indices(), max)
};
if width <= max {
return Ok(s);
} else if rtl && idx == 0 {
return Ok(s);
} else if !rtl && lossy[idx..].chars().nth(1).is_none() {
return Ok(s);
}
let result: Vec<_> = if rtl {
let i = lossy[idx..].char_indices().nth(1).map(|(i, _)| idx + i).unwrap_or(lossy.len());
"".bytes().chain(lossy[i..].bytes()).collect()
} else {
lossy[..idx].bytes().chain("".bytes()).collect()
};
lua.create_string(result)
})
}