use std::collections::BTreeMap;
use ucd_parse::{self, Codepoint, NameAlias, UnicodeData};
use ucd_util;
use crate::args::ArgMatches;
use crate::error::Result;
pub fn command(args: ArgMatches<'_>) -> Result<()> {
let dir = args.ucd_dir()?;
let data = ucd_parse::parse_by_codepoint(&dir)?;
let aliases = if args.is_present("no-aliases") {
None
} else {
Some(ucd_parse::parse_many_by_codepoint(&dir)?)
};
let mut names = names_to_codepoint(
&data,
&aliases,
!args.is_present("no-ideograph"),
!args.is_present("no-hangul"),
);
if args.is_present("normalize") {
names = names
.into_iter()
.map(|(mut name, tagged)| {
ucd_util::character_name_normalize(&mut name);
(name, tagged)
})
.collect();
}
let mut wtr = args.writer("names")?;
if args.is_present("tagged") {
let mut map = BTreeMap::new();
for (name, (tag, cp)) in names {
map.insert(name, tag.with_codepoint(cp));
}
wtr.string_to_u64(args.name(), &map)?;
} else {
let mut map = BTreeMap::new();
for (name, (_, cp)) in names {
map.insert(name, cp);
}
wtr.string_to_codepoint(args.name(), &map)?;
}
Ok(())
}
#[derive(Debug)]
enum NameTag {
Explicit,
Alias,
Hangul,
Ideograph,
}
impl NameTag {
fn with_codepoint(&self, cp: u32) -> u64 {
use self::NameTag::*;
match *self {
Explicit => (1 << 33) | (cp as u64),
Alias => (1 << 34) | (cp as u64),
Hangul => (1 << 35) | (cp as u64),
Ideograph => (1 << 36) | (cp as u64),
}
}
}
fn names_to_codepoint(
data: &BTreeMap<Codepoint, UnicodeData>,
aliases: &Option<BTreeMap<Codepoint, Vec<NameAlias>>>,
ideograph: bool,
hangul: bool,
) -> BTreeMap<String, (NameTag, u32)> {
let mut map = BTreeMap::new();
if let Some(ref alias_map) = *aliases {
for (cp, aliases) in alias_map {
for name_alias in aliases {
let v = (NameTag::Alias, cp.value());
map.insert(name_alias.alias.clone(), v);
}
}
}
for (cp, datum) in data {
let isnull = datum.name.is_empty()
|| (datum.name.starts_with('<') && datum.name.ends_with('>'));
if !isnull {
let v = (NameTag::Explicit, cp.value());
map.insert(datum.name.clone(), v);
}
}
if ideograph {
for &(start, end) in ucd_util::RANGE_IDEOGRAPH {
for cp in start..end + 1 {
let v = (NameTag::Ideograph, cp);
map.insert(ucd_util::ideograph_name(cp).unwrap(), v);
}
}
}
if hangul {
for &(start, end) in ucd_util::RANGE_HANGUL_SYLLABLE {
for cp in start..end + 1 {
let v = (NameTag::Hangul, cp);
map.insert(ucd_util::hangul_name(cp).unwrap(), v);
}
}
}
map
}