include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
pub fn to_ipf(pua: char) -> Option<&'static str> {
TABLE.get(&pua).cloned()
}
pub fn is_pua(pua: char) -> bool {
(0xE0BC..=0xF8F7).contains(&(pua as u32))
}
pub fn to_ipf_string<'a>(pua_str: &'a str) -> std::borrow::Cow<'a, str> {
let pua_index = pua_str.find(is_pua);
if let Some(index) = pua_index {
let (non_pua, mut pua_str) = pua_str.split_at(index);
let mut buffer = non_pua.to_owned();
loop {
let non_pua_index = pua_str.find(|letter| !is_pua(letter));
match non_pua_index {
Some(non_pua_index) => {
let (pua, non_pua) = pua_str.split_at(non_pua_index);
pua.chars()
.flat_map(to_ipf)
.for_each(|ipf| buffer.push_str(ipf));
pua_str = non_pua;
}
None => {
pua_str
.chars()
.flat_map(to_ipf)
.for_each(|ipf| buffer.push_str(ipf));
break std::borrow::Cow::Owned(buffer);
}
}
let pua_index = pua_str.find(is_pua);
match pua_index {
Some(pua_index) => {
let (non_pua, pua) = pua_str.split_at(pua_index);
buffer.push_str(non_pua);
pua_str = pua;
}
None => {
buffer.push_str(pua_str);
break std::borrow::Cow::Owned(buffer);
}
}
}
} else {
std::borrow::Cow::Borrowed(pua_str)
}
}
pub struct IpfIterator<'a> {
chars: std::str::Chars<'a>,
buffer: std::str::Chars<'static>,
}
impl<'a> Iterator for IpfIterator<'a> {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
if let Some(next_ipf) = self.buffer.next() {
Some(next_ipf)
} else {
if let Some(new_char) = self.chars.next() {
if let Some(ipf) = to_ipf(new_char) {
self.buffer = ipf.chars();
self.next()
} else {
Some(new_char)
}
} else {
None
}
}
}
}
pub trait IntoIpfIterator<'a> {
fn ipf_iter(&'a self) -> IpfIterator<'a>;
}
impl IntoIpfIterator<'_> for str {
fn ipf_iter(&self) -> IpfIterator {
IpfIterator {
chars: self.chars(),
buffer: "".chars(),
}
}
}