use crate::shape::*;
use alloc::vec::Vec;
pub fn is_javanese(c: &u16) -> bool {
*c >= 0xA980 && *c <= 0xA9DF
}
#[derive(Debug, Clone, PartialEq)]
enum MType {
C, GB, H, IV, J, M, MR, MY, N, O, P, R, S, VAbv, VBlw, VPre, VPst, VS, WJ, NJ, WS, }
impl MType {
fn from_u16(c: &u16) -> MType {
match c {
0xA984 | 0xA989..=0xA98B | 0xA98F..=0xA9B2 => MType::C,
0x00A0 | 0x00D7 | 0x2012..=0x2015 | 0x2022 | 0x25CC | 0x25FB..=0x25FE => MType::GB,
0xA9C0 => MType::H,
0xA985..=0xA988 | 0xA98C..=0xA98E => MType::IV,
0x200D | 0x034F => MType::J,
0xA980..=0xA983 => MType::M,
0xA9BF => MType::MR,
0xA9BE => MType::MY,
0xA9B3 => MType::N,
0xA9C1..=0xA9CD => MType::P,
0xA9CE | 0xA9DA..=0xA9DD => MType::R,
0xA9CF | 0xA9DE | 0xA9DF => MType::S,
0xA9B6 | 0xA9B7 | 0xA9BC => MType::VAbv,
0xA9B8 | 0xA9B9 => MType::VBlw,
0xA9BA | 0xA9BB => MType::VPre,
0xA9B4 | 0xA9B5 | 0xA9BD => MType::VPst,
0xFE00..=0xFE0F => MType::VS,
0x2060 => MType::WJ,
0x200C => MType::NJ,
&WHITESPACE => MType::WS,
_ => MType::O,
}
}
fn is_same(&self, other: &u16) -> bool {
let other_type = MType::from_u16(other);
*self == other_type || other_type == MType::J
}
}
#[derive(Clone)]
struct Definition<'a> {
m_type: MType,
code: &'a [u16],
}
impl<'a> Definition<'a> {
fn new(m_type: MType, code: &'a [u16]) -> Self {
Self { m_type, code }
}
fn build_definition(input: &[u16]) -> Vec<Definition> {
let mut clusters = Vec::new();
let mut idx: usize = 0;
while idx < input.len() {
let start_idx = idx;
let code = &input[idx];
let m_type = MType::from_u16(code);
let mut end_idx = idx + 1;
while end_idx < input.len() && MType::is_same(&m_type, &input[end_idx]) {
end_idx += 1;
}
clusters.push(Definition::new(m_type, &input[start_idx..end_idx]));
idx = end_idx;
}
clusters
}
}
struct Cluster<'a> {
pub defs: Vec<Definition<'a>>,
pub whitespace: Option<&'a u16>,
}
impl<'a> Cluster<'a> {
fn new(defs: Vec<Definition<'a>>, whitespace: Option<&'a u16>) -> Self {
Self { defs, whitespace }
}
fn build_clusters(defs: &'a [Definition<'a>]) -> Vec<Cluster<'a>> {
let mut clusters = Vec::new();
let mut def_idx = 0;
for idx in 0..defs.len() {
if defs[idx].m_type == MType::WS || defs[idx].m_type == MType::NJ {
clusters.push(Cluster::new(defs[def_idx..idx].to_vec(), Some(&defs[idx].code[0])));
def_idx = idx + 1;
}
}
if def_idx < defs.len() {
clusters.push(Cluster::new(defs[def_idx..].to_vec(), None));
}
clusters
}
fn get_sorted(&mut self) -> Vec<u16> {
let mut idx: usize = 0;
while idx < self.defs.len() {
match self.defs[idx].m_type {
MType::VPre => {
let v_pre = self.defs.remove(idx);
self.defs.insert(0, v_pre);
}
MType::VAbv | MType::VBlw | MType::VPst => {
}
_ => {}
}
idx += 1;
}
let mut reordered = Vec::with_capacity(self.defs.len());
for def in &self.defs {
reordered.extend_from_slice(def.code)
}
reordered
}
}
pub fn shape_javanese(input: &mut [u16]) {
let mut res: Vec<u16> = Vec::with_capacity(input.len());
let defs = Definition::build_definition(input);
let mut clusters_sets = Cluster::build_clusters(&defs);
clusters_sets.iter_mut().for_each(|c| {
res.append(&mut c.get_sorted());
if let Some(ws) = c.whitespace {
res.push(*ws);
}
});
input.copy_from_slice(&res[..input.len()]);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn javanese_test() {
let input: &[u16] = &[0xA98F, 0xA9C0, 0xA98F, 0xA9BF, 0xA9BE, 0xA9BA, 0xA9BA, 0xA9B7];
let expected: &[u16] = &[0xA9BA, 0xA9BA, 0xA98F, 0xA9C0, 0xA98F, 0xA9BF, 0xA9BE, 0xA9B7];
let mut result = input.to_vec();
shape_javanese(&mut result);
assert_eq!(result, expected);
}
#[test]
fn javanese_2_test() {
let input = "ꦧꦺꦲꦏ꧀ꦠꦸꦩꦿꦥ꧀ꦲ";
let expected: &[u16] =
&[43450, 43431, 43442, 43407, 43456, 43424, 43448, 43433, 43455, 43429, 43456, 43442];
let input_utf16_slice: Vec<u16> = input.encode_utf16().collect();
let input_utf16_ref: &[u16] = &input_utf16_slice;
let mut result = input_utf16_ref.to_vec();
shape_javanese(&mut result);
assert_eq!(result, expected);
}
}