unic_ucd_normal/decomposition.rs
1// Copyright 2012-2015 The Rust Project Developers.
2// Copyright 2017 The UNIC Project Developers.
3//
4// See the COPYRIGHT file at the top-level directory of this distribution.
5//
6// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9// option. This file may not be copied, modified, or distributed
10// except according to those terms.
11
12use core::ops::FnMut;
13
14use crate::composition::{canonical_decomposition, compatibility_decomposition};
15
16use unic_ucd_hangul::{decompose_syllable, is_syllable};
17
18/// Compute canonical Unicode decomposition for character.
19///
20/// See [Unicode Standard Annex #15](https://www.unicode.org/reports/tr15/) for more information.
21pub fn decompose_canonical<F>(ch: char, mut callback: F)
22where
23 F: FnMut(char),
24{
25 d(ch, &mut callback, false);
26}
27
28/// Compute canonical or compatible Unicode decomposition for character.
29///
30/// See [Unicode Standard Annex #15](https://www.unicode.org/reports/tr15/) for more information.
31pub fn decompose_compatible<F>(ch: char, mut callback: F)
32where
33 F: FnMut(char),
34{
35 d(ch, &mut callback, true);
36}
37
38// FIXME: This is a workaround, we should use `F` instead of `&mut F`
39fn d<F>(ch: char, callback: &mut F, k: bool)
40where
41 F: FnMut(char),
42{
43 // 7-bit ASCII never decomposes
44 if ch <= '\x7f' {
45 (*callback)(ch);
46 return;
47 }
48
49 // Perform decomposition for Hangul
50 if is_syllable(ch) {
51 decompose_syllable(ch, callback);
52 return;
53 }
54
55 // First check the canonical decompositions
56 if let Some(canon) = canonical_decomposition(ch) {
57 for x in canon {
58 d(*x, callback, k);
59 }
60 return;
61 }
62
63 // Bottom out if we're not doing compat.
64 if !k {
65 (*callback)(ch);
66 return;
67 }
68
69 // Then check the compatibility decompositions
70 if let Some(compat) = compatibility_decomposition(ch) {
71 for x in compat {
72 d(*x, callback, k);
73 }
74 return;
75 }
76
77 // Finally bottom out.
78 (*callback)(ch);
79}