use unicode_width::UnicodeWidthStr;
use xutf::{Utf8, Utf16, Utf32, width, width_char, width_str, width_within, width_within_str};
const CORPUS: &[&str] = &[
"plain printable ASCII 0123456789 !@#$%^&*()",
"Cafe\u{301} nai\u{308}ve A\u{30a}",
"Ελληνικά Кириллица",
"漢字界面 日本語 カタカナ ひらがな",
"abc アイウ カタカナ",
"한글 각 값 가 각 ㄱㄴㅏㅣ \u{3164}",
"नमस्ते हिन्दी தமிழ் ภาษาไทย",
"┌─┬─┐│╳│└─┴─┘",
"😀 🐈 🚀 ✅ 🌍",
"⚠️ ℹ️ ❤️",
"0️⃣ #️⃣",
"👨👩👧 👩❤️👩 👨👨👦👦",
"👋🏽 👍🏻 🧑🏿",
"🇺🇸 🇯🇵 🇩🇪",
"🏴\u{e0067}\u{e0062}\u{e0065}\u{e006e}\u{e0067}\u{e007f}",
];
fn reference(s: &str) -> usize {
UnicodeWidthStr::width(s)
}
#[test]
fn safe_corpus_matches_unicode_width() {
for &s in CORPUS {
assert_eq!(width_str(s), reference(s), "{s:?}");
}
let mut state = 0x8e5d_a2c7_13b9_4f61u64;
for _ in 0..500 {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
let count = 2 + (state as usize % 7);
let mut s = String::new();
for _ in 0..count {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
s.push_str(CORPUS[state as usize % CORPUS.len()]);
s.push(' ');
}
assert_eq!(width_str(&s), reference(&s), "{s:?}");
}
}
#[test]
fn deterministic_safe_scalar_fuzz_matches_unicode_width() {
const SAFE: &[char] = &[
' ', '!', '0', 'A', 'z', 'é', 'Ω', 'Ж', '\u{301}', '\u{308}', 'क', 'म', '\u{93f}', '\u{94d}',
'த', '\u{bbf}', 'ก', '\u{e34}', '界', '語', 'あ', 'カ', 'カ', '한', 'ᄀ', 'ᅡ', 'ᆨ', 'ㄱ',
'\u{3164}', '─', '│', '╳', '😀', '✅', '🚀', '👋', '🏽', '🇺', '🇸',
];
let mut state = 0xd1b5_4a32_d192_ed03u64;
for _ in 0..2_000 {
state = state
.wrapping_mul(2862933555777941757)
.wrapping_add(3037000493);
let len = state as usize % 40;
let mut s = String::new();
for _ in 0..len {
state = state
.wrapping_mul(2862933555777941757)
.wrapping_add(3037000493);
s.push(SAFE[state as usize % SAFE.len()]);
}
assert_eq!(width_str(&s), reference(&s), "{s:?}");
}
}
#[test]
fn all_encodings_measure_the_same_width() {
for &s in CORPUS {
let utf16: Vec<u16> = s.encode_utf16().collect();
let utf32: Vec<u32> = s.chars().map(u32::from).collect();
let utf16_foreign: Vec<u16> = utf16.iter().map(|u| u.swap_bytes()).collect();
let utf32_foreign: Vec<u32> = utf32.iter().map(|u| u.swap_bytes()).collect();
let expected = width::<Utf8>(s.as_bytes());
assert_eq!(width::<Utf16<false>>(&utf16), expected, "{s:?}");
assert_eq!(width::<Utf32<false>>(&utf32), expected, "{s:?}");
assert_eq!(width::<Utf16<true>>(&utf16_foreign), expected, "{s:?}");
assert_eq!(width::<Utf32<true>>(&utf32_foreign), expected, "{s:?}");
}
}
#[test]
fn simd_boundaries_and_cluster_backoff() {
const LENGTHS: &[usize] = &[1, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129];
for &k in LENGTHS {
assert_eq!(width_str(&"x".repeat(k)), k);
let keycap = "0".repeat(k) + "0\u{fe0f}\u{20e3}";
assert_eq!(width_str(&keycap), k + 2, "keycap after {k} units");
let promoted = "0".repeat(k) + "\u{fe0f}";
assert_eq!(width_str(&promoted), k + 1, "VS16 after {k} units");
let text_base = "x".repeat(k) + "\u{fe0f}\u{20e3}";
assert_eq!(width_str(&text_base), k, "non-keycap base after {k} units");
let tab = "x".repeat(k) + "\t";
let bell = "x".repeat(k) + "\x07";
assert_eq!(width_str(&tab), k);
assert_eq!(width_str(&bell), k);
}
}
#[test]
fn tui_reference_widths() {
for (s, expected) in [
("⚠️", 2),
("⚠", 1),
("✅", 2),
("0️⃣", 2),
("a\tb", 2),
("界", 2),
("\u{3164}", 0),
("e\u{301}", 1),
("🇺🇸", 2),
("👨👩👧", 2),
("", 0),
] {
assert_eq!(width_str(s), expected, "{s:?}");
}
}
#[test]
fn bounded_width_matches_unbounded_measurement() {
for (s, budgets) in [
("", &[0, 1][..]),
("ascii", &[0, 4, 5, 6]),
("a somewhat longer printable ASCII line", &[0, 8, 20, 38, 39]),
("漢字a", &[0, 1, 2, 4, 5]),
("👨👩👧 and text", &[0, 1, 2, 5, 10]),
("ab\u{301}", &[0, 1, 2]),
] {
let expected = width_str(s);
for &max_width in budgets {
let bounded = width_within_str(s, max_width);
assert_eq!(bounded, (expected <= max_width).then_some(expected), "{s:?} at {max_width}");
assert_eq!(width_within::<Utf8>(s.as_bytes(), max_width), bounded, "{s:?} at {max_width}");
}
}
let long = "x".repeat(1024 * 1024);
assert_eq!(width_within_str(&long, 80), None);
}
#[test]
fn bounded_width_includes_zero_width_tail_at_edge() {
assert_eq!(width_within_str("", 0), Some(0));
assert_eq!(width_within_str("a", 0), None);
assert_eq!(width_within_str("ab\u{301}", 2), Some(2));
assert_eq!(width_within_str("ab\u{301}", 1), None);
let exact = "界e\u{301}😀";
let exact_width = width_str(exact);
assert_eq!(width_within_str(exact, exact_width), Some(exact_width));
}
#[test]
fn bounded_width_matches_utf16() {
let sample = "ASCII 漢字 e\u{301} 👨👩👧";
let utf16: Vec<u16> = sample.encode_utf16().collect();
for max_width in 0..=width_str(sample) + 1 {
assert_eq!(
width_within::<Utf16<false>>(&utf16, max_width),
width_within_str(sample, max_width),
"budget {max_width}"
);
}
}
#[test]
fn standalone_character_widths() {
for (c, expected) in [
('a', 1),
('\t', 0),
('\n', 0),
('\r', 0),
('中', 2),
('\u{301}', 0),
('\u{2764}', 1),
('\u{1f600}', 2),
('\u{200d}', 0),
] {
assert_eq!(width_char(c), expected, "{c:?}");
}
}