use crate::shape::*;
use alloc::vec::Vec;
pub fn is_myanmar(c: &u16) -> bool {
*c >= 0x1000 && *c <= 0x109F ||
*c >= 0xAA60 && *c <= 0xAA7F ||
*c >= 0xA9E0 && *c <= 0xA9FF
}
#[derive(Clone, PartialEq)]
enum MType {
A, C,
K, MR, O, VBlw, VPre, WS, }
impl MType {
fn from_u16(c: &u16, may_be_kinzi_sequence: bool) -> MType {
if may_be_kinzi_sequence {
return match c {
0x1004 | 0x101B | 0x105A => MType::K,
_ => Self::from_u16(c, false),
};
}
match c {
0x1032 | 0x1036 => MType::A,
0x1000..=0x1020
| 0x103F
| 0x104E
| 0x01050
| 0x01051
| 0x105A..=0x105D
| 0x1061
| 0x1065
| 0x1066
| 0x106E..=0x1070
| 0x1075..=0x1081
| 0x108E
| 0xAA60..=0xAA6F
| 0xAA71..=0xAA76
| 0xAA7A => MType::C,
0x103C => MType::MR,
0x102F | 0x1030 | 0x1058 | 0x1059 => MType::VBlw,
0x1031 | 0x1084 => MType::VPre,
&WHITESPACE => MType::WS,
_ => MType::O,
}
}
}
#[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_from_unicodes(input: &[u16]) -> Vec<Definition> {
let mut clusters = Vec::new();
let mut idx: usize = 0;
while idx < input.len() {
let code = &input[idx];
let may_be_kinzi_sequence: bool =
idx + 2 < input.len() && input[idx + 1] == 0x103A && input[idx + 2] == 0x1039;
clusters.push(Definition::new(MType::from_u16(code, may_be_kinzi_sequence), code));
if may_be_kinzi_sequence {
idx += 3;
} else {
idx += 1;
}
}
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 {
clusters.push(Cluster::new(defs[def_idx..idx].to_vec(), Some(defs[idx].code)));
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::K => {
if idx + 1 < self.defs.len() {
self.defs.swap(idx, idx + 1);
idx += 1;
}
}
MType::MR => {
let mut base_c_idx = 0;
while base_c_idx + 1 < self.defs.len()
&& self.defs[base_c_idx].m_type != MType::C
{
base_c_idx += 1;
}
if base_c_idx != idx {
let v_pre = self.defs.remove(idx);
self.defs.insert(base_c_idx, v_pre);
}
}
MType::VPre => {
let v_pre = self.defs.remove(idx);
self.defs.insert(0, v_pre);
}
MType::A => {
let mut prev_idx = idx;
while prev_idx - 1 > 0 && self.defs[prev_idx - 1].m_type == MType::VBlw {
prev_idx -= 1;
}
if prev_idx != idx {
self.defs.swap(prev_idx, idx);
}
}
_ => {}
}
idx += 1;
}
let mut reordered = Vec::with_capacity(self.defs.len());
for def in &self.defs {
match def.m_type {
MType::K => {
reordered.extend_from_slice(&[*def.code, 0x103A, 0x1039]);
}
_ => reordered.push(*def.code),
}
}
reordered
}
}
pub fn shape_myanmar(input: &mut [u16]) {
let mut res: Vec<u16> = Vec::with_capacity(input.len());
let defs = Definition::build_from_unicodes(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 myanmar_complex_2_test() {
let input: &[u16] = &[
0x1004, 0x103A, 0x1039, 0x1000, 0x1039, 0x1000, 0x103B, 0x103C, 0x103D, 0x1031, 0x1031,
0x102D, 0x102F, 0x1036, 0x102C, 0x1036,
];
let expected: &[u16] = &[
0x1031, 0x1031, 0x103C, 0x1000, 0x1004, 0x103A, 0x1039, 0x1039, 0x1000, 0x103B, 0x103D,
0x102D, 0x1036, 0x102F, 0x102C, 0x1036,
];
let mut result = input.to_vec();
shape_myanmar(&mut result);
assert_eq!(result, expected);
}
#[test]
fn myanmar_complex_test() {
let input = "င်္က္ကျြွှေို့်ာှီ့ၤဲံ့းႍ";
let expected: &[u16] = &[
4145, 4156, 4096, 4100, 4154, 4153, 4153, 4096, 4155, 4157, 4158, 4141, 4143, 4151,
4154, 4140, 4158, 4142, 4151, 4196, 4146, 4150, 4151, 4152, 4237,
];
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_myanmar(&mut result);
assert_eq!(result, expected);
}
#[test]
fn myanmar_complex_3_test() {
let input = "မြန်မာ"; let expected: &[u16] = &[4156, 4121, 4116, 4154, 4121, 4140];
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_myanmar(&mut result);
assert_eq!(result, expected);
}
}