runtestdata/
runtestdata.rs1extern crate xi_unicode;
21
22use xi_unicode::{LineBreakIterator, LineBreakLeafIter};
23
24use std::fs::File;
25use std::io::prelude::*;
26use std::io::BufReader;
27
28fn quote_str(s: &str) -> String {
29 let mut result = String::new();
30 for c in s.chars() {
31 if c == '"' || c == '\\' {
32 result.push('\\');
33 }
34 if ' ' <= c && c <= '~' {
35 result.push(c);
36 } else {
37 result.push_str(&format!("\\u{{{:04x}}}", c as u32));
38 }
39 }
40 result
41}
42
43fn check_breaks(s: &str, breaks: &[usize]) -> bool {
44 let my_breaks = LineBreakIterator::new(s).map(|(bk, _hard)| bk).collect::<Vec<_>>();
45 if my_breaks != breaks {
46 println!("failed case: \"{}\"", quote_str(s));
47 println!("expected {:?} actual {:?}", breaks, my_breaks);
48 return false;
49 }
50 true
51}
52
53fn check_lb(s: &str) -> bool {
55 let breaks = LineBreakIterator::new(s).collect::<Vec<_>>();
56 for i in 0..breaks.len() - 1 {
57 let mut cursor = LineBreakLeafIter::new(s, breaks[i].0);
58 for &bk in &breaks[i + 1..] {
59 let mut next = cursor.next(s);
60 if next.0 == s.len() {
61 next = (s.len(), true);
62 }
63 if next != bk {
64 println!("failed case: \"{}\"", quote_str(s));
65 println!("expected {:?} actual {:?}", bk, next);
66 return false;
67 }
68 }
69 }
70 true
71}
72
73fn run_test(filename: &str, lb: bool) -> std::io::Result<()> {
74 let f = File::open(filename)?;
75 let mut reader = BufReader::new(f);
76 let mut pass = 0;
77 let mut total = 0;
78 loop {
79 let mut line = String::new();
80 if reader.read_line(&mut line)? == 0 {
81 break;
82 };
83 let mut s = String::new();
84 let mut breaks = Vec::new();
85 for token in line.split_whitespace() {
86 if token == "÷" {
87 breaks.push(s.len());
88 } else if token == "×" {
89 } else if token == "#" {
90 break;
91 } else if let Ok(cp) = u32::from_str_radix(token, 16) {
92 s.push(std::char::from_u32(cp).unwrap());
93 }
94 }
95 total += 1;
96 if lb {
97 if check_lb(&s) {
98 pass += 1;
99 }
100 } else {
101 if check_breaks(&s, &breaks) {
102 pass += 1;
103 }
104 }
105 }
106 println!("{}/{} pass", pass, total);
107 Ok(())
108}
109
110fn main() {
111 let mut args = std::env::args();
112 let _ = args.next();
113 let filename = args.next().unwrap();
114 match args.next() {
115 None => {
116 let _ = run_test(&filename, false);
117 }
118 Some(ref s) if s == "--lookbehind" => {
119 let _ = run_test(&filename, true);
120 }
121 _ => {
122 println!("unknown argument");
123 }
124 }
125}