16e652d70Sopenharmony_ciuse std::collections::BTreeSet as Set; 26e652d70Sopenharmony_ciuse std::fs; 36e652d70Sopenharmony_ciuse std::io::{self, Write}; 46e652d70Sopenharmony_ciuse std::path::Path; 56e652d70Sopenharmony_ciuse std::process; 66e652d70Sopenharmony_ci 76e652d70Sopenharmony_cipub struct Properties { 86e652d70Sopenharmony_ci xid_start: Set<u32>, 96e652d70Sopenharmony_ci xid_continue: Set<u32>, 106e652d70Sopenharmony_ci} 116e652d70Sopenharmony_ci 126e652d70Sopenharmony_ciimpl Properties { 136e652d70Sopenharmony_ci pub fn is_xid_start(&self, ch: char) -> bool { 146e652d70Sopenharmony_ci self.xid_start.contains(&(ch as u32)) 156e652d70Sopenharmony_ci } 166e652d70Sopenharmony_ci 176e652d70Sopenharmony_ci pub fn is_xid_continue(&self, ch: char) -> bool { 186e652d70Sopenharmony_ci self.xid_continue.contains(&(ch as u32)) 196e652d70Sopenharmony_ci } 206e652d70Sopenharmony_ci} 216e652d70Sopenharmony_ci 226e652d70Sopenharmony_cipub fn parse_xid_properties(ucd_dir: &Path) -> Properties { 236e652d70Sopenharmony_ci let mut properties = Properties { 246e652d70Sopenharmony_ci xid_start: Set::new(), 256e652d70Sopenharmony_ci xid_continue: Set::new(), 266e652d70Sopenharmony_ci }; 276e652d70Sopenharmony_ci 286e652d70Sopenharmony_ci let filename = "DerivedCoreProperties.txt"; 296e652d70Sopenharmony_ci let path = ucd_dir.join(filename); 306e652d70Sopenharmony_ci let contents = fs::read_to_string(path).unwrap_or_else(|err| { 316e652d70Sopenharmony_ci let suggestion = 326e652d70Sopenharmony_ci "Download from https://www.unicode.org/Public/zipped/l5.0.0/UCD.zip and unzip."; 336e652d70Sopenharmony_ci let _ = writeln!(io::stderr(), "{}: {err}\n{suggestion}", ucd_dir.display()); 346e652d70Sopenharmony_ci process::exit(1); 356e652d70Sopenharmony_ci }); 366e652d70Sopenharmony_ci 376e652d70Sopenharmony_ci for (i, line) in contents.lines().enumerate() { 386e652d70Sopenharmony_ci if line.starts_with('#') || line.trim().is_empty() { 396e652d70Sopenharmony_ci continue; 406e652d70Sopenharmony_ci } 416e652d70Sopenharmony_ci let (lo, hi, name) = parse_line(line).unwrap_or_else(|| { 426e652d70Sopenharmony_ci let _ = writeln!(io::stderr(), "{filename} line {i} is unexpected:\n{line}"); 436e652d70Sopenharmony_ci process::exit(1); 446e652d70Sopenharmony_ci }); 456e652d70Sopenharmony_ci let set = match name { 466e652d70Sopenharmony_ci "XID_Start" => &mut properties.xid_start, 476e652d70Sopenharmony_ci "XID_Continue" => &mut properties.xid_continue, 486e652d70Sopenharmony_ci _ => continue, 496e652d70Sopenharmony_ci }; 506e652d70Sopenharmony_ci set.extend(lo..=hi); 516e652d70Sopenharmony_ci } 526e652d70Sopenharmony_ci 536e652d70Sopenharmony_ci properties 546e652d70Sopenharmony_ci} 556e652d70Sopenharmony_ci 566e652d70Sopenharmony_cifn parse_line(line: &str) -> Option<(u32, u32, &str)> { 576e652d70Sopenharmony_ci let (mut codepoint, rest) = line.split_once(';')?; 586e652d70Sopenharmony_ci 596e652d70Sopenharmony_ci let (lo, hi); 606e652d70Sopenharmony_ci codepoint = codepoint.trim(); 616e652d70Sopenharmony_ci if let Some((a, b)) = codepoint.split_once("..") { 626e652d70Sopenharmony_ci lo = parse_codepoint(a)?; 636e652d70Sopenharmony_ci hi = parse_codepoint(b)?; 646e652d70Sopenharmony_ci } else { 656e652d70Sopenharmony_ci lo = parse_codepoint(codepoint)?; 666e652d70Sopenharmony_ci hi = lo; 676e652d70Sopenharmony_ci } 686e652d70Sopenharmony_ci 696e652d70Sopenharmony_ci let name = rest.trim().split('#').next()?.trim_end(); 706e652d70Sopenharmony_ci Some((lo, hi, name)) 716e652d70Sopenharmony_ci} 726e652d70Sopenharmony_ci 736e652d70Sopenharmony_cifn parse_codepoint(s: &str) -> Option<u32> { 746e652d70Sopenharmony_ci u32::from_str_radix(s, 16).ok() 756e652d70Sopenharmony_ci} 76