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 {
|
fn count_to_letter_code(mut count: usize) -> String {
|
||||||
let mut letters = Vec::new();
|
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 {
|
loop {
|
||||||
let letter_idx = (count % 26) as u32;
|
let letter_idx = (count % 26) as u8;
|
||||||
letters.push(char::from_u32('A' as u32 + letter_idx).unwrap());
|
letters.push(b'A' + letter_idx);
|
||||||
count /= 26;
|
count /= 26;
|
||||||
|
|
||||||
if count == 0 {
|
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 {
|
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