1#![warn(missing_docs)]
7#![warn(unreachable_pub)]
8
9mod builtin;
10mod error;
11mod grapheme;
12mod pattern;
13mod rasm;
14mod resolve;
15
16#[cfg(test)]
17mod tests;
18
19pub use builtin::{builtin_pattern_set, is_builtin_pattern_set};
20pub use error::{CompileError, CompileErrorKind};
21pub use pattern::{compile_pattern_text, PatternSet};
22
23use grapheme::{is_bare_tatweel_at, joined_runs, split_graphemes, KASHIDA};
24use resolve::resolve_run;
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28pub struct KashidaPoint {
29 pub index: u32,
31 pub priority: u8,
33}
34
35pub fn find_kashida_points_patterns(word: &str, set: &PatternSet) -> Vec<KashidaPoint> {
37 let graphemes = split_graphemes(word);
38 let mut out = Vec::new();
39 for run in joined_runs(&graphemes) {
40 out.extend(resolve_run(&graphemes, &run, set));
41 }
42 out
43}
44
45fn strip_bare_tatweel(word: &str) -> String {
46 if !word.contains(KASHIDA) {
47 return word.to_string();
48 }
49 let chars: Vec<char> = word.chars().collect();
50 let mut out = String::with_capacity(word.len());
51 for k in 0..chars.len() {
52 if is_bare_tatweel_at(&chars, k) {
53 continue;
54 }
55 out.push(chars[k]);
56 }
57 out
58}
59
60pub fn find_kashida_points(
80 word: &str,
81 set: &PatternSet,
82 remove_existing_kashida: bool,
83) -> (String, Vec<KashidaPoint>) {
84 let cleaned = if remove_existing_kashida {
85 strip_bare_tatweel(word)
86 } else {
87 word.to_string()
88 };
89 let points = find_kashida_points_patterns(&cleaned, set);
90 (cleaned, points)
91}