Skip to content

Commit 8e880b9

Browse files
committed
cformat: Fix a bug when formatting unicode strings
String::len() returns number of bytes and not number of chars, so it doens't work as expected for unicode strings. Also, added a test that would have triggered the bug.
1 parent e374aff commit 8e880b9

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

vm/src/cformat.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl CFormatSpec {
100100
fill_char: char,
101101
num_prefix_chars: Option<usize>,
102102
) -> String {
103-
let mut num_chars = string.len();
103+
let mut num_chars = string.chars().count();
104104
if let Some(num_prefix_chars) = num_prefix_chars {
105105
num_chars = num_chars + num_prefix_chars;
106106
}
@@ -128,8 +128,8 @@ impl CFormatSpec {
128128
let mut string = string;
129129
// truncate if needed
130130
if let Some(CFormatQuantity::Amount(precision)) = self.precision {
131-
if string.len() > precision {
132-
string.truncate(precision);
131+
if string.chars().count() > precision {
132+
string = string.chars().take(precision).collect::<String>();
133133
}
134134
}
135135
self.fill_string(string, ' ', None)
@@ -186,7 +186,7 @@ impl CFormatSpec {
186186
format!(
187187
"{}{}",
188188
prefix,
189-
self.fill_string(magnitude_string, fill_char, Some(prefix.len()))
189+
self.fill_string(magnitude_string, fill_char, Some(prefix.chars().count()))
190190
)
191191
} else {
192192
self.fill_string(format!("{}{}", prefix, magnitude_string), ' ', None)
@@ -322,7 +322,7 @@ fn parse_literal(text: &str) -> Result<(CFormatPart, &str, usize), ParsingError>
322322
Ok((
323323
CFormatPart::Literal(result_string.to_string()),
324324
"",
325-
text.len(),
325+
text.chars().count(),
326326
))
327327
}
328328

@@ -638,6 +638,17 @@ mod tests {
638638
);
639639
}
640640

641+
#[test]
642+
fn test_parse_and_format_unicode_string() {
643+
assert_eq!(
644+
"%.2s"
645+
.parse::<CFormatSpec>()
646+
.unwrap()
647+
.format_string("❤❤❤❤❤❤❤❤".to_string()),
648+
"❤❤".to_string()
649+
);
650+
}
651+
641652
#[test]
642653
fn test_parse_and_format_number() {
643654
assert_eq!(

0 commit comments

Comments
 (0)