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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user