use std::char;
use std::collections::BTreeSet;
use std::io::{self, BufRead, Write};
use std::u32;
pub fn process_confusables<R: BufRead, W: Write>(
input: R,
mut output: W,
) -> io::Result<()> {
let mut chars = BTreeSet::<char>::new();
let mut strs = BTreeSet::<String>::new();
for line in input.lines().skip(1).filter_map(|line| {
if let Ok(line) = line {
Some(line)
} else {
None
}
}) {
let line = if let Some(comment_begin) = line.find('#') {
&line[..comment_begin]
} else {
&line
};
if line.len() > 0 {
let mut line_chunks = line.split(" ;\t");
let from = line_chunks.next().expect("Failed to parse line");
let tos = line_chunks.next().expect("Failed to parse line");
let from = u32::from_str_radix(from, 16)
.expect("Failed to parse `from` as hex");
let tos: Vec<u32> = tos
.split(" ")
.map(|to| {
u32::from_str_radix(to, 16)
.expect("Failed to parse `to` as hex")
})
.collect();
chars.insert(char::from_u32(from).unwrap());
if tos.len() == 1 {
chars.insert(char::from_u32(tos[0]).unwrap());
} else {
strs.insert(
tos.iter().map(|&i| char::from_u32(i).unwrap()).collect(),
);
}
}
}
output.write(b"/// A set of all characters that may be confusable\n")?;
output.write(b"/// with other strings or characters.\n")?;
output.write(
&format!("pub const CONFUSABLES_CHARS: [char; {}] = [\n", chars.len())
.as_bytes(),
)?;
for ch in chars {
output
.write(&format!(" '\\u{{{:04x}}}',\n", ch as u32).as_bytes())?;
}
output.write(b"];\n\n")?;
output.write(b"/// A set of all strings that may be confusable\n")?;
output.write(b"/// with other strings or characters.\n")?;
output.write(
&format!("pub const CONFUSABLES_STRS: [&str; {}] = [\n", strs.len())
.as_bytes(),
)?;
for s in strs {
output.write(b" \"")?;
for ch in s.chars() {
output.write(&format!("\\u{{{:04x}}}", ch as u32).as_bytes())?;
}
output.write(b"\",\n")?;
}
output.write(b"];\n")?;
Ok(())
}