use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
pub trait UnicodeTruncate {
fn trunc(&self, width: usize) -> String;
}
impl UnicodeTruncate for str {
#[inline]
fn trunc(&self, width: usize) -> String {
if self.width() <= width {
String::from(self)
} else {
let mut length: usize = 0;
let mut result = String::new();
for grapheme in self.graphemes(true) {
let grapheme_length = grapheme.width();
length += grapheme_length;
if length > width {
break;
};
result.push_str(grapheme);
}
result
}
}
}
#[cfg(test)]
mod tests_trunc {
use super::UnicodeTruncate;
#[test]
fn truncate_correct_despite_several_multibyte_chars() {
assert_eq!(String::from("r͂o͒͜w̾").trunc(2), String::from("r͂o͒͜"));
}
#[test]
fn truncate_at_end_returns_complete_string() {
assert_eq!(String::from("r͂o͒͜w̾").trunc(3), String::from("r͂o͒͜w̾"));
}
#[test]
fn truncate_behind_end_returns_complete_string() {
assert_eq!(String::from("r͂o͒͜w̾").trunc(4), String::from("r͂o͒͜w̾"));
}
#[test]
fn truncate_at_zero_returns_empty_string() {
assert_eq!(String::from("r͂o͒͜w̾").trunc(0), String::from(""));
}
#[test]
fn truncate_correct_despite_fullwidth_character() {
assert_eq!(String::from("a🌕bc").trunc(4), String::from("a🌕b"));
}
#[test]
fn truncate_within_fullwidth_character_truncates_before_the_character() {
assert_eq!(String::from("a🌕").trunc(2), String::from("a"));
}
}