use crate::lookup::in_ranges;
use crate::tables;
#[inline]
#[must_use]
pub fn char_width(c: char) -> usize {
let cp = c as u32;
if cp < 0x20 || (0x7F..0xA0).contains(&cp) {
return 0;
}
if in_ranges(cp, tables::ZERO_WIDTH) {
return 0;
}
if in_ranges(cp, tables::WIDE) {
return 2;
}
1
}
#[inline]
#[must_use]
pub fn str_width(s: &str) -> usize {
s.chars().map(char_width).sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ascii_printable_is_one() {
for c in '\u{20}'..='\u{7E}' {
assert_eq!(char_width(c), 1, "{c:?}");
}
}
#[test]
fn test_controls_are_zero() {
assert_eq!(char_width('\0'), 0);
assert_eq!(char_width('\t'), 0);
assert_eq!(char_width('\n'), 0);
assert_eq!(char_width('\u{1B}'), 0); assert_eq!(char_width('\u{7F}'), 0); assert_eq!(char_width('\u{85}'), 0); }
#[test]
fn test_wide_cjk_is_two() {
assert_eq!(char_width('世'), 2);
assert_eq!(char_width('界'), 2);
assert_eq!(char_width('\u{FF21}'), 2); }
#[test]
fn test_combining_marks_are_zero() {
assert_eq!(char_width('\u{0301}'), 0);
assert_eq!(char_width('\u{0300}'), 0);
assert_eq!(char_width('\u{200B}'), 0); }
#[test]
fn test_soft_hyphen_is_one() {
assert_eq!(char_width('\u{00AD}'), 1);
}
#[test]
fn test_str_width_sums() {
assert_eq!(str_width(""), 0);
assert_eq!(str_width("abc"), 3);
assert_eq!(str_width("a世b"), 4);
assert_eq!(str_width("e\u{0301}"), 1);
}
}