improve count_to_letter_code

- reserve the complete required length at the beginning to reduce reallocations
- use u8 instead of char so that we can re-use the allocation for the string
This commit is contained in:
Skgland
2025-11-18 21:42:10 +01:00
committed by Bennet Bleßmann
parent 119761ad10
commit a0b4162d7a

View File

@@ -159,9 +159,14 @@ impl Term {
fn count_to_letter_code(mut count: usize) -> String {
let mut letters = Vec::new();
// +2 rather than +1 to account for the _ at the end
let length = count.checked_ilog(26).unwrap_or(0) as usize + 2;
letters.reserve(length);
loop {
let letter_idx = (count % 26) as u32;
letters.push(char::from_u32('A' as u32 + letter_idx).unwrap());
let letter_idx = (count % 26) as u8;
letters.push(b'A' + letter_idx);
count /= 26;
if count == 0 {
@@ -169,7 +174,15 @@ fn count_to_letter_code(mut count: usize) -> String {
}
}
letters.into_iter().chain("_".chars()).rev().collect()
letters.push(b'_');
debug_assert_eq!(length, letters.len());
letters.reverse();
// Safety: we only push ascii chars A-Z and _
// an ascii only byte sequence is always valid utf-8
unsafe { String::from_utf8_unchecked(letters) }
}
impl Term {
@@ -623,3 +636,11 @@ impl Machine {
}
}
}
#[test]
fn test_count_to_letter_code() {
for idx in 0..1000 {
// ensure the debug assert doesn't trigger
count_to_letter_code(idx);
}
}