1use std::path::Path;
2use std::str::FromStr;
3
4use crate::common::{
5 parse_codepoint_association, CodepointIter, Codepoints, UcdFile,
6 UcdFileByCodepoint,
7};
8use crate::error::Error;
9
10/// A single row in the `EastAsianWidth.txt` file, describing the value of the
11/// `East_Asian_Width` property.
12///
13/// Note: All code points, assigned or unassigned, that are not listed in
14/// EastAsianWidth.txt file are given the value "N".
15#[derive(Clone, Debug, Default, Eq, PartialEq)]
16pub struct EastAsianWidth {
17 /// The codepoint or codepoint range for this entry.
18 pub codepoints: Codepoints,
19 /// One of "A", "F", "H", "N", "Na", "W".
20 pub width: String,
21}
22
23impl UcdFile for EastAsianWidth {
24 fn relative_file_path() -> &'static Path {
25 Path::new("EastAsianWidth.txt")
26 }
27}
28
29impl UcdFileByCodepoint for EastAsianWidth {
30 fn codepoints(&self) -> CodepointIter {
31 self.codepoints.into_iter()
32 }
33}
34
35impl FromStr for EastAsianWidth {
36 type Err = Error;
37
38 fn from_str(line: &str) -> Result<EastAsianWidth, Error> {
39 let (codepoints: Codepoints, width: &str) = parse_codepoint_association(line)?;
40 Ok(EastAsianWidth { codepoints, width: width.to_string() })
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::EastAsianWidth;
47
48 #[test]
49 fn parse_single() {
50 let line = "27E7;Na # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET\n";
51 let row: EastAsianWidth = line.parse().unwrap();
52 assert_eq!(row.codepoints, 0x27E7);
53 assert_eq!(row.width, "Na");
54 }
55
56 #[test]
57 fn parse_range() {
58 let line = "1F57B..1F594;N # So [26] LEFT HAND TELEPHONE RECEIVER..REVERSED VICTORY HAND\n";
59 let row: EastAsianWidth = line.parse().unwrap();
60 assert_eq!(row.codepoints, (0x1F57B, 0x1F594));
61 assert_eq!(row.width, "N");
62 }
63}
64