1use std::path::Path;
2use std::str::FromStr;
3
4use crate::common::{
5 parse_break_test, parse_codepoint_association, CodepointIter, Codepoints,
6 UcdFile, UcdFileByCodepoint,
7};
8use crate::error::Error;
9
10/// A single row in the `auxiliary/SentenceBreakProperty.txt` file.
11#[derive(Clone, Debug, Default, Eq, PartialEq)]
12pub struct SentenceBreak {
13 /// The codepoint or codepoint range for this entry.
14 pub codepoints: Codepoints,
15 /// The property value assigned to the codepoints in this entry.
16 pub value: String,
17}
18
19impl UcdFile for SentenceBreak {
20 fn relative_file_path() -> &'static Path {
21 Path::new("auxiliary/SentenceBreakProperty.txt")
22 }
23}
24
25impl UcdFileByCodepoint for SentenceBreak {
26 fn codepoints(&self) -> CodepointIter {
27 self.codepoints.into_iter()
28 }
29}
30
31impl FromStr for SentenceBreak {
32 type Err = Error;
33
34 fn from_str(line: &str) -> Result<SentenceBreak, Error> {
35 let (codepoints: Codepoints, value: &str) = parse_codepoint_association(line)?;
36 Ok(SentenceBreak { codepoints, value: value.to_string() })
37 }
38}
39
40/// A single row in the `auxiliary/SentenceBreakTest.txt` file.
41///
42/// This file defines tests for the sentence break algorithm.
43#[derive(Clone, Debug, Default, Eq, PartialEq)]
44pub struct SentenceBreakTest {
45 /// Each string is a UTF-8 encoded group of codepoints that make up a
46 /// single sentence.
47 pub sentences: Vec<String>,
48 /// A human readable description of this test.
49 pub comment: String,
50}
51
52impl UcdFile for SentenceBreakTest {
53 fn relative_file_path() -> &'static Path {
54 Path::new("auxiliary/SentenceBreakTest.txt")
55 }
56}
57
58impl FromStr for SentenceBreakTest {
59 type Err = Error;
60
61 fn from_str(line: &str) -> Result<SentenceBreakTest, Error> {
62 let (groups: Vec, comment: String) = parse_break_test(line)?;
63 Ok(SentenceBreakTest { sentences: groups, comment })
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::{SentenceBreak, SentenceBreakTest};
70
71 #[test]
72 fn parse_single() {
73 let line = "11445 ; Extend # Mc NEWA SIGN VISARGA\n";
74 let row: SentenceBreak = line.parse().unwrap();
75 assert_eq!(row.codepoints, 0x11445);
76 assert_eq!(row.value, "Extend");
77 }
78
79 #[test]
80 fn parse_range() {
81 let line = "FE31..FE32 ; SContinue # Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH\n";
82 let row: SentenceBreak = line.parse().unwrap();
83 assert_eq!(row.codepoints, (0xFE31, 0xFE32));
84 assert_eq!(row.value, "SContinue");
85 }
86
87 #[test]
88 fn parse_test() {
89 let line = "÷ 2060 × 5B57 × 2060 × 002E × 2060 ÷ 5B57 × 2060 × 2060 ÷ # ÷ [0.2] WORD JOINER (Format_FE) × [998.0] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) × [5.0] WORD JOINER (Format_FE) × [998.0] FULL STOP (ATerm) × [5.0] WORD JOINER (Format_FE) ÷ [11.0] CJK UNIFIED IDEOGRAPH-5B57 (OLetter) × [5.0] WORD JOINER (Format_FE) × [5.0] WORD JOINER (Format_FE) ÷ [0.3]";
90
91 let row: SentenceBreakTest = line.parse().unwrap();
92 assert_eq!(
93 row.sentences,
94 vec![
95 "\u{2060}\u{5B57}\u{2060}\u{002E}\u{2060}",
96 "\u{5B57}\u{2060}\u{2060}",
97 ]
98 );
99 assert!(row.comment.contains("[5.0] WORD JOINER (Format_FE)"));
100 }
101}
102