use core::fmt::{self, Debug};
use unicode_script::{Script, ScriptExtension};
#[derive(Copy, Clone, PartialEq, Hash, Eq)]
pub struct AugmentedScriptSet {
pub base: ScriptExtension,
pub hanb: bool,
pub jpan: bool,
pub kore: bool,
}
impl From<ScriptExtension> for AugmentedScriptSet {
fn from(ext: ScriptExtension) -> Self {
let mut hanb = false;
let mut jpan = false;
let mut kore = false;
if ext.is_common() || ext.is_inherited() || ext.contains_script(Script::Han) {
hanb = true;
jpan = true;
kore = true;
} else {
if ext.contains_script(Script::Hiragana) || ext.contains_script(Script::Katakana) {
jpan = true;
}
if ext.contains_script(Script::Hangul) {
kore = true;
}
if ext.contains_script(Script::Bopomofo) {
hanb = true;
}
}
Self {
base: ext,
hanb,
jpan,
kore,
}
}
}
impl From<char> for AugmentedScriptSet {
fn from(c: char) -> Self {
AugmentedScriptSet::for_char(c)
}
}
impl From<&'_ str> for AugmentedScriptSet {
fn from(s: &'_ str) -> Self {
AugmentedScriptSet::for_str(s)
}
}
impl Default for AugmentedScriptSet {
fn default() -> Self {
AugmentedScriptSet {
base: Script::Common.into(),
hanb: true,
jpan: true,
kore: true,
}
}
}
impl Debug for AugmentedScriptSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_empty() {
write!(f, "AugmentedScriptSet {{∅}}")?;
} else if self.is_all() {
write!(f, "AugmentedScriptSet {{ALL}}")?;
} else {
write!(f, "AugmentedScriptSet {{")?;
let mut first_entry = true;
let hanb = if self.hanb { Some("Hanb") } else { None };
let jpan = if self.jpan { Some("Jpan") } else { None };
let kore = if self.kore { Some("Kore") } else { None };
for writing_system in None
.into_iter()
.chain(hanb)
.chain(jpan)
.chain(kore)
.chain(self.base.iter().map(Script::short_name))
{
if !first_entry {
write!(f, ", ")?;
} else {
first_entry = false;
}
write!(f, "{}", writing_system)?;
}
write!(f, "}}")?;
}
Ok(())
}
}
impl fmt::Display for AugmentedScriptSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_empty() {
write!(f, "Empty")?;
} else if self.is_all() {
write!(f, "All")?;
} else {
let mut first_entry = true;
let hanb = if self.hanb {
Some("Han with Bopomofo")
} else {
None
};
let jpan = if self.jpan { Some("Japanese") } else { None };
let kore = if self.kore { Some("Korean") } else { None };
for writing_system in None
.into_iter()
.chain(hanb)
.chain(jpan)
.chain(kore)
.chain(self.base.iter().map(Script::full_name))
{
if !first_entry {
write!(f, ", ")?;
} else {
first_entry = false;
}
write!(f, "{}", writing_system)?;
}
}
Ok(())
}
}
impl AugmentedScriptSet {
pub fn intersect_with(&mut self, other: Self) {
self.base.intersect_with(other.base);
self.hanb = self.hanb && other.hanb;
self.jpan = self.jpan && other.jpan;
self.kore = self.kore && other.kore;
}
pub fn is_empty(&self) -> bool {
self.base.is_empty() && !self.hanb && !self.jpan && !self.kore
}
pub fn is_all(&self) -> bool {
self.base.is_common() || self.base.is_inherited()
}
pub fn for_char(c: char) -> Self {
ScriptExtension::from(c).into()
}
pub fn for_str(s: &str) -> Self {
let mut set = AugmentedScriptSet::default();
for ch in s.chars() {
set.intersect_with(ch.into())
}
set
}
}
pub trait MixedScript {
fn is_single_script(self) -> bool;
fn resolve_script_set(self) -> AugmentedScriptSet;
}
impl MixedScript for &'_ str {
fn is_single_script(self) -> bool {
!AugmentedScriptSet::for_str(self).is_empty()
}
fn resolve_script_set(self) -> AugmentedScriptSet {
self.into()
}
}
pub fn is_potential_mixed_script_confusable_char(c: char) -> bool {
use crate::tables::potential_mixed_script_confusable::potential_mixed_script_confusable;
potential_mixed_script_confusable(c)
}