use std::collections::{BTreeMap, BTreeSet};
use ucd_parse::{self, ArabicShaping};
use crate::args::ArgMatches;
use crate::error::Result;
use crate::general_category;
use crate::util::PropertyValues;
pub fn command(args: ArgMatches<'_>) -> Result<()> {
let dir = args.ucd_dir()?;
let propvals = PropertyValues::from_ucd_dir(&dir)?;
let rows: Vec<ArabicShaping> = ucd_parse::parse(&dir)?;
let unexpanded_gc = ucd_parse::parse(&dir)?;
let gc =
general_category::expand_into_categories(unexpanded_gc, &propvals)?;
let mut by_type: BTreeMap<String, BTreeSet<u32>> = BTreeMap::new();
let mut assigned = BTreeSet::new();
for row in rows {
assigned.insert(row.codepoint.value());
let jt =
propvals.canonical("jt", row.joining_type.as_str())?.to_string();
by_type
.entry(jt)
.or_insert(BTreeSet::new())
.insert(row.codepoint.value());
}
let transparent_name = propvals.canonical("jt", "transparent")?;
let non_joining_name = propvals.canonical("jt", "non_joining")?;
let transparent_categories = ["Mn", "Me", "Cf"]
.iter()
.map(|cat| propvals.canonical("gc", cat).map(|name| &gc[&name]))
.collect::<Result<Vec<_>>>()?;
for cp in 0..=0x10FFFF {
if assigned.contains(&cp) {
continue;
}
if transparent_categories.iter().any(|cat| cat.contains(&cp)) {
by_type.get_mut(&transparent_name).unwrap().insert(cp);
} else {
by_type.get_mut(&non_joining_name).unwrap().insert(cp);
}
}
let mut wtr = args.writer("joining_type")?;
if args.is_present("enum") {
wtr.ranges_to_enum(args.name(), &by_type)?;
} else if args.is_present("rust-enum") {
let variants = by_type.keys().map(String::as_str).collect::<Vec<_>>();
wtr.ranges_to_rust_enum(args.name(), &variants, &by_type)?;
} else if args.is_present("combined") {
wtr.ranges_to_combined(args.name(), &by_type)?;
} else {
wtr.names(by_type.keys())?;
for (name, set) in by_type {
wtr.ranges(&name, &set)?;
}
}
Ok(())
}