1use std::collections::HashMap;
6
7use super::bidi_class::BidiClass;
8use super::bidi_data::{clear_then_reset_if_too_large, BidiData};
9use super::bidi_paired_bracket_type::BidiPairedBracketType;
10
11const MAX_PAIRED_BRACKET_DEPTH: usize = 63;
13
14#[derive(Debug)]
30pub struct BidiAlgorithm {
31 has_clean_state: bool,
33
34 has_brackets: bool,
36
37 has_embeddings: bool,
39
40 has_isolates: bool,
42
43 isolate_pairs: HashMap<usize, usize>,
48
49 working_classes: Vec<BidiClass>,
51
52 resolved_levels: Vec<i8>,
54
55 paragraph_embedding_level: i8,
57
58 status_stack: Vec<Status>,
61
62 x9_map: Vec<usize>,
64
65 level_runs: Vec<LevelRun>,
67
68 isolated_run_mapping: Vec<usize>,
71
72 pending_isolate_openings: Vec<usize>,
74
75 pending_opening_brackets: Vec<usize>,
78
79 paired_brackets: Vec<BracketPair>,
81}
82
83impl Default for BidiAlgorithm {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl BidiAlgorithm {
90 pub fn new() -> Self {
92 Self {
93 has_clean_state: true,
94 has_brackets: false,
95 has_embeddings: false,
96 has_isolates: false,
97 isolate_pairs: HashMap::new(),
98 working_classes: Vec::new(),
99 resolved_levels: Vec::new(),
100 paragraph_embedding_level: 0,
101 status_stack: Vec::new(),
102 x9_map: Vec::new(),
103 level_runs: Vec::new(),
104 isolated_run_mapping: Vec::new(),
105 pending_isolate_openings: Vec::new(),
106 pending_opening_brackets: Vec::new(),
107 paired_brackets: Vec::new(),
108 }
109 }
110
111 #[inline]
116 pub fn resolved_levels(&self) -> &[i8] {
117 &self.resolved_levels
118 }
119
120 #[inline]
122 pub fn resolved_paragraph_embedding_level(&self) -> i32 {
123 self.paragraph_embedding_level as i32
124 }
125
126 pub fn process(&mut self, data: &mut BidiData) {
133 let paragraph_embedding_level = data.paragraph_embedding_level();
134 let has_brackets = data.has_brackets();
135 let has_embeddings = data.has_embeddings();
136 let has_isolates = data.has_isolates();
137 let (classes, paired_bracket_types, paired_bracket_values) = data.parts_mut();
138
139 self.process_classes(
140 classes,
141 paired_bracket_types,
142 paired_bracket_values,
143 paragraph_embedding_level,
144 has_brackets,
145 has_embeddings,
146 has_isolates,
147 None,
148 );
149 }
150
151 #[allow(clippy::too_many_arguments)]
155 pub fn process_classes(
156 &mut self,
157 types: &mut [BidiClass],
158 paired_bracket_types: &[BidiPairedBracketType],
159 paired_bracket_values: &[i32],
160 paragraph_embedding_level: i8,
161 has_brackets: Option<bool>,
162 has_embeddings: Option<bool>,
163 has_isolates: Option<bool>,
164 out_levels: Option<&mut [i8]>,
165 ) {
166 self.reset();
168
169 if types.is_empty() {
170 return;
171 }
172
173 self.has_clean_state = false;
174
175 self.working_classes.extend_from_slice(types);
177
178 self.has_brackets = has_brackets.unwrap_or(paired_bracket_types.len() == types.len());
180 self.has_embeddings = has_embeddings.unwrap_or(true);
181 self.has_isolates = has_isolates.unwrap_or(true);
182
183 self.find_isolate_pairs(types);
185
186 if paragraph_embedding_level == 2 {
188 self.paragraph_embedding_level = self.resolve_embedding_level_at(types, 0);
189 } else {
190 self.paragraph_embedding_level = paragraph_embedding_level;
191 }
192
193 match out_levels {
195 Some(out_levels) => {
196 if out_levels.len() != types.len() {
197 panic!("Out levels must be the same length as the input data");
198 }
199
200 self.resolve(types, paired_bracket_types, paired_bracket_values, out_levels);
201 }
202 None => {
203 let mut resolved_levels = std::mem::take(&mut self.resolved_levels);
206 resolved_levels.clear();
207 resolved_levels.resize(types.len(), self.paragraph_embedding_level);
208
209 self.resolve(types, paired_bracket_types, paired_bracket_values, &mut resolved_levels);
210
211 self.resolved_levels = resolved_levels;
212 }
213 }
214 }
215
216 fn resolve(
218 &mut self,
219 original_classes: &mut [BidiClass],
220 paired_bracket_types: &[BidiPairedBracketType],
221 paired_bracket_values: &[i32],
222 resolved_levels: &mut [i8],
223 ) {
224 self.resolve_explicit_embedding_levels(original_classes, resolved_levels);
226
227 self.build_x9_removal_map(original_classes);
229
230 self.process_isolated_run_sequences(original_classes, paired_bracket_types, paired_bracket_values, resolved_levels);
232
233 self.reset_whitespace_levels(original_classes, resolved_levels);
235
236 self.assign_levels_to_code_points_removed_by_x9(original_classes, resolved_levels);
238 }
239
240 pub fn resolve_embedding_level(&self, data: &[BidiClass]) -> i8 {
249 self.resolve_embedding_level_at(data, 0)
250 }
251
252 fn resolve_embedding_level_at(&self, data: &[BidiClass], data_start: usize) -> i8 {
255 let mut i = 0;
257 while i < data.len() {
258 match data[i] {
259 BidiClass::LeftToRight => {
260 return 0;
262 }
263
264 BidiClass::ArabicLetter | BidiClass::RightToLeft => {
265 return 1;
267 }
268
269 BidiClass::FirstStrongIsolate | BidiClass::LeftToRightIsolate | BidiClass::RightToLeftIsolate => {
270 match self.isolate_pairs.get(&(data_start + i)) {
274 Some(&end) => i = end.saturating_sub(data_start),
277 None => i = data.len(),
278 }
279 }
280
281 _ => {}
282 }
283
284 i += 1;
285 }
286
287 0
289 }
290
291 fn find_isolate_pairs(&mut self, original_classes: &[BidiClass]) {
294 if !self.has_isolates {
296 return;
297 }
298
299 self.has_isolates = false;
303
304 self.pending_isolate_openings.clear();
306
307 for (i, &t) in original_classes.iter().enumerate() {
308 match t {
309 BidiClass::LeftToRightIsolate | BidiClass::RightToLeftIsolate | BidiClass::FirstStrongIsolate => {
310 self.pending_isolate_openings.push(i);
311 self.has_isolates = true;
312 }
313 BidiClass::PopDirectionalIsolate => {
314 if let Some(opening) = self.pending_isolate_openings.pop() {
315 self.isolate_pairs.insert(opening, i);
316 }
317
318 self.has_isolates = true;
319 }
320 _ => {}
321 }
322 }
323 }
324
325 fn resolve_explicit_embedding_levels(&mut self, original_classes: &[BidiClass], resolved_levels: &mut [i8]) {
328 if !self.has_isolates && !self.has_embeddings {
330 return;
331 }
332
333 self.status_stack.clear();
335 let mut overflow_isolate_count = 0;
336 let mut overflow_embedding_count = 0;
337 let mut valid_isolate_count = 0;
338
339 const MAX_STACK_DEPTH: i8 = 125;
341
342 self.status_stack.clear();
344
345 self.status_stack.push(Status::new(self.paragraph_embedding_level, BidiClass::OtherNeutral, false));
347
348 #[inline(always)]
349 fn peek(stack: &[Status]) -> Status {
350 *stack.last().expect("the status stack is never empty")
351 }
352
353 #[inline(always)]
354 fn next_odd_level(level: i8) -> i8 {
355 ((level as i32 + 1) | 1) as i8
356 }
357
358 #[inline(always)]
359 fn next_even_level(level: i8) -> i8 {
360 ((level as i32 + 2) & !1) as i8
361 }
362
363 for i in 0..original_classes.len() {
365 match original_classes[i] {
366 BidiClass::RightToLeftEmbedding => {
367 let new_level = next_odd_level(peek(&self.status_stack).embedding_level);
369 if new_level <= MAX_STACK_DEPTH && overflow_isolate_count == 0 && overflow_embedding_count == 0 {
370 self.status_stack.push(Status::new(new_level, BidiClass::OtherNeutral, false));
371 resolved_levels[i] = new_level;
372 } else if overflow_isolate_count == 0 {
373 overflow_embedding_count += 1;
374 }
375 }
376
377 BidiClass::LeftToRightEmbedding => {
378 let new_level = next_even_level(peek(&self.status_stack).embedding_level);
380 if new_level < MAX_STACK_DEPTH && overflow_isolate_count == 0 && overflow_embedding_count == 0 {
381 self.status_stack.push(Status::new(new_level, BidiClass::OtherNeutral, false));
382 resolved_levels[i] = new_level;
383 } else if overflow_isolate_count == 0 {
384 overflow_embedding_count += 1;
385 }
386 }
387
388 BidiClass::RightToLeftOverride => {
389 let new_level = next_odd_level(peek(&self.status_stack).embedding_level);
391 if new_level <= MAX_STACK_DEPTH && overflow_isolate_count == 0 && overflow_embedding_count == 0 {
392 self.status_stack.push(Status::new(new_level, BidiClass::RightToLeft, false));
393 resolved_levels[i] = new_level;
394 } else if overflow_isolate_count == 0 {
395 overflow_embedding_count += 1;
396 }
397 }
398
399 BidiClass::LeftToRightOverride => {
400 let new_level = next_even_level(peek(&self.status_stack).embedding_level);
402 if new_level <= MAX_STACK_DEPTH && overflow_isolate_count == 0 && overflow_embedding_count == 0 {
403 self.status_stack.push(Status::new(new_level, BidiClass::LeftToRight, false));
404 resolved_levels[i] = new_level;
405 } else if overflow_isolate_count == 0 {
406 overflow_embedding_count += 1;
407 }
408 }
409
410 BidiClass::RightToLeftIsolate | BidiClass::LeftToRightIsolate | BidiClass::FirstStrongIsolate => {
411 let mut resolved_isolate = original_classes[i];
413
414 if resolved_isolate == BidiClass::FirstStrongIsolate {
415 let end_of_isolate = match self.isolate_pairs.get(&i) {
416 Some(&end_of_isolate) => end_of_isolate,
417 None => original_classes.len(),
418 };
419
420 if self.resolve_embedding_level_at(&original_classes[i + 1..end_of_isolate], i + 1) == 1 {
422 resolved_isolate = BidiClass::RightToLeftIsolate;
423 } else {
424 resolved_isolate = BidiClass::LeftToRightIsolate;
425 }
426 }
427
428 let tos = peek(&self.status_stack);
430 resolved_levels[i] = tos.embedding_level;
431
432 if tos.override_status != BidiClass::OtherNeutral {
434 self.working_classes[i] = tos.override_status;
435 }
436
437 let new_level = if resolved_isolate == BidiClass::RightToLeftIsolate {
439 next_odd_level(tos.embedding_level)
440 } else {
441 next_even_level(tos.embedding_level)
442 };
443
444 if new_level <= MAX_STACK_DEPTH && overflow_isolate_count == 0 && overflow_embedding_count == 0 {
446 valid_isolate_count += 1;
447 self.status_stack.push(Status::new(new_level, BidiClass::OtherNeutral, true));
448 } else {
449 overflow_isolate_count += 1;
450 }
451 }
452
453 BidiClass::BoundaryNeutral => {
454 }
457
458 BidiClass::PopDirectionalIsolate => {
459 if overflow_isolate_count > 0 {
461 overflow_isolate_count -= 1;
462 } else if valid_isolate_count != 0 {
463 overflow_embedding_count = 0;
464 while !peek(&self.status_stack).isolate_status {
465 self.status_stack.pop();
466 }
467
468 self.status_stack.pop();
469 valid_isolate_count -= 1;
470 }
471
472 let tos = peek(&self.status_stack);
473 resolved_levels[i] = tos.embedding_level;
474 if tos.override_status != BidiClass::OtherNeutral {
475 self.working_classes[i] = tos.override_status;
476 }
477 }
478
479 BidiClass::PopDirectionalFormat => {
480 if overflow_isolate_count == 0 {
482 if overflow_embedding_count > 0 {
483 overflow_embedding_count -= 1;
484 } else if !peek(&self.status_stack).isolate_status && self.status_stack.len() >= 2 {
485 self.status_stack.pop();
486 }
487 }
488 }
489
490 BidiClass::ParagraphSeparator => {
491 resolved_levels[i] = self.paragraph_embedding_level;
493 }
494
495 _ => {
496 let tos = peek(&self.status_stack);
498 resolved_levels[i] = tos.embedding_level;
499 if tos.override_status != BidiClass::OtherNeutral {
500 self.working_classes[i] = tos.override_status;
501 }
502 }
503 }
504 }
505 }
506
507 fn build_x9_removal_map(&mut self, original_classes: &[BidiClass]) {
510 self.x9_map.clear();
512 self.x9_map.reserve(original_classes.len());
513
514 if self.has_embeddings || self.has_isolates {
515 for (i, &original_class) in original_classes.iter().enumerate() {
517 if !is_removed_by_x9(original_class) {
518 self.x9_map.push(i);
519 }
520 }
521 } else {
522 self.x9_map.extend(0..original_classes.len());
523 }
524 }
525
526 #[inline(always)]
532 fn map_x9(&self, index: usize) -> usize {
533 self.x9_map[index]
534 }
535
536 fn add_level_run(
545 &mut self,
546 start: usize,
547 length: usize,
548 level: i32,
549 original_classes: &[BidiClass],
550 resolved_levels: &[i8],
551 ) {
552 let first_char_index = self.map_x9(start);
554 let last_char_index = self.map_x9(start + length - 1);
555
556 let prev_level = original_classes[..first_char_index]
558 .iter()
559 .rposition(|&original_class| !is_removed_by_x9(original_class))
560 .map_or(self.paragraph_embedding_level as i32, |i| resolved_levels[i] as i32);
561 let sos = direction_from_level(prev_level.max(level));
562
563 let last_type = self.working_classes[last_char_index];
565 let next_level = if is_isolate_start(last_type) {
566 self.paragraph_embedding_level as i32
567 } else {
568 let mut i = last_char_index + 1;
569 while i < original_classes.len() && is_removed_by_x9(original_classes[i]) {
570 i += 1;
571 }
572
573 if i >= original_classes.len() {
574 self.paragraph_embedding_level as i32
575 } else {
576 resolved_levels[i] as i32
577 }
578 };
579
580 let eos = direction_from_level(next_level.max(level));
581
582 self.level_runs.push(LevelRun::new(start, length, level, sos, eos));
584 }
585
586 fn find_level_runs(&mut self, original_classes: &[BidiClass], resolved_levels: &[i8]) {
589 let mut current_level: i32 = -1;
590 let mut run_start = 0;
591 for i in 0..self.x9_map.len() {
592 let level = resolved_levels[self.map_x9(i)] as i32;
593 if level == current_level {
594 continue;
595 }
596
597 if current_level != -1 {
598 self.add_level_run(run_start, i - run_start, current_level, original_classes, resolved_levels);
599 }
600
601 current_level = level;
602 run_start = i;
603 }
604
605 if current_level != -1 {
607 self.add_level_run(
608 run_start,
609 self.x9_map.len() - run_start,
610 current_level,
611 original_classes,
612 resolved_levels,
613 );
614 }
615 }
616
617 fn find_run_for_index(&self, index: usize) -> usize {
623 for i in 0..self.level_runs.len() {
624 if self.map_x9(self.level_runs[i].start) == index {
628 return i;
629 }
630 }
631
632 panic!("Internal error");
633 }
634
635 fn process_isolated_run_sequences(
637 &mut self,
638 original_classes: &mut [BidiClass],
639 paired_bracket_types: &[BidiPairedBracketType],
640 paired_bracket_values: &[i32],
641 resolved_levels: &mut [i8],
642 ) {
643 self.find_level_runs(original_classes, resolved_levels);
645
646 while !self.level_runs.is_empty() {
653 self.isolated_run_mapping.clear();
655
656 let mut run_index = 0;
658 let mut eos;
659 let sos = self.level_runs[0].sos;
660 let level = self.level_runs[0].level;
661 loop {
662 let r = self.level_runs.remove(run_index);
665
666 eos = r.eos;
669
670 self.isolated_run_mapping.extend_from_slice(&self.x9_map[r.start..r.start + r.length]);
673
674 let last_character_index = self.isolated_run_mapping[self.isolated_run_mapping.len() - 1];
677 let last_type = original_classes[last_character_index];
678 let next_run_index =
679 if is_isolate_start(last_type) { self.isolate_pairs.get(&last_character_index).copied() } else { None };
680
681 match next_run_index {
682 Some(next_run_index) => {
683 run_index = self.find_run_for_index(next_run_index);
685 }
686 None => break,
687 }
688 }
689
690 self.process_isolated_run_sequence(
692 sos,
693 eos,
694 level,
695 original_classes,
696 paired_bracket_types,
697 paired_bracket_values,
698 resolved_levels,
699 );
700 }
701 }
702
703 #[allow(clippy::too_many_arguments)]
706 fn process_isolated_run_sequence(
707 &mut self,
708 sos: BidiClass,
709 eos: BidiClass,
710 run_level: i32,
711 original_classes: &mut [BidiClass],
712 paired_bracket_types: &[BidiPairedBracketType],
713 paired_bracket_values: &[i32],
714 resolved_levels: &mut [i8],
715 ) {
716 let has_brackets = self.has_brackets;
717
718 let mut run = IsolatedRun {
720 map: &self.isolated_run_mapping,
721 resolved_classes: &mut self.working_classes,
722 original_classes,
723 levels: resolved_levels,
724 paired_bracket_types,
725 paired_bracket_values,
726 level: run_level,
727 direction: direction_from_level(run_level),
728 length: self.isolated_run_mapping.len(),
729 };
730 let run_length = run.length;
731
732 let mut previous_class = sos;
735
736 const ISOLATE_MASK: u32 = (1u32 << BidiClass::LeftToRightIsolate as i32)
737 | (1u32 << BidiClass::RightToLeftIsolate as i32)
738 | (1u32 << BidiClass::FirstStrongIsolate as i32)
739 | (1u32 << BidiClass::PopDirectionalIsolate as i32);
740
741 const W_RULES_MASK: u32 = (1u32 << BidiClass::EuropeanNumber as i32)
742 | (1u32 << BidiClass::ArabicLetter as i32)
743 | (1u32 << BidiClass::EuropeanSeparator as i32)
744 | (1u32 << BidiClass::CommonSeparator as i32)
745 | (1u32 << BidiClass::ArabicNumber as i32)
746 | (1u32 << BidiClass::EuropeanTerminator as i32);
747
748 let mut w_rules: u32 = 0;
749
750 for i in 0..run_length {
751 let resolved_class = run.resolved_class(i);
752
753 if resolved_class == BidiClass::NonspacingMark {
754 run.set_resolved_class(i, previous_class);
755 } else {
756 let class_bit = 1u32 << resolved_class as i32;
757
758 if (class_bit & ISOLATE_MASK) != 0 {
759 previous_class = BidiClass::OtherNeutral;
760 } else {
761 w_rules |= class_bit & W_RULES_MASK;
762 previous_class = resolved_class;
763 }
764 }
765 }
766
767 let has_en = (w_rules & (1u32 << BidiClass::EuropeanNumber as i32)) != 0;
770 let has_al = (w_rules & (1u32 << BidiClass::ArabicLetter as i32)) != 0;
771 let has_es = (w_rules & (1u32 << BidiClass::EuropeanSeparator as i32)) != 0;
772 let has_cs = (w_rules & (1u32 << BidiClass::CommonSeparator as i32)) != 0;
773 let mut has_an = (w_rules & (1u32 << BidiClass::ArabicNumber as i32)) != 0;
774 let has_et = (w_rules & (1u32 << BidiClass::EuropeanTerminator as i32)) != 0;
775
776 if has_en {
778 for i in 0..run_length {
779 if run.resolved_class(i) != BidiClass::EuropeanNumber {
780 continue;
781 }
782
783 for j in (0..i).rev() {
784 let resolved_class = run.resolved_class(j);
785
786 match resolved_class {
787 BidiClass::LeftToRight | BidiClass::RightToLeft | BidiClass::ArabicLetter => {
788 if resolved_class == BidiClass::ArabicLetter {
789 run.set_resolved_class(i, BidiClass::ArabicNumber);
790 has_an = true;
791 }
792
793 break;
794 }
795 _ => {}
796 }
797 }
798 }
799 }
800
801 if has_al {
803 for i in 0..run_length {
804 if run.resolved_class(i) == BidiClass::ArabicLetter {
805 run.set_resolved_class(i, BidiClass::RightToLeft);
806 }
807 }
808 }
809
810 if (has_es || has_cs) && (has_en || has_an) {
812 let mut i = 1;
813 while i + 1 < run_length {
814 let resolved_class = run.resolved_class(i);
815
816 if resolved_class == BidiClass::EuropeanSeparator {
817 let previous_separator_class = run.resolved_class(i - 1);
818 let next_separator_class = run.resolved_class(i + 1);
819
820 if previous_separator_class == BidiClass::EuropeanNumber
821 && next_separator_class == BidiClass::EuropeanNumber
822 {
823 run.set_resolved_class(i, BidiClass::EuropeanNumber);
825 }
826 } else if resolved_class == BidiClass::CommonSeparator {
827 let previous_separator_class = run.resolved_class(i - 1);
828 let next_separator_class = run.resolved_class(i + 1);
829
830 if (previous_separator_class == BidiClass::ArabicNumber
831 && next_separator_class == BidiClass::ArabicNumber)
832 || (previous_separator_class == BidiClass::EuropeanNumber
833 && next_separator_class == BidiClass::EuropeanNumber)
834 {
835 run.set_resolved_class(i, previous_separator_class);
837 }
838 }
839
840 i += 1;
841 }
842 }
843
844 if has_et && has_en {
846 let mut i = 0;
847 while i < run_length {
848 if run.resolved_class(i) != BidiClass::EuropeanTerminator {
849 i += 1;
850 continue;
851 }
852
853 let sequence_start = i;
855 let mut sequence_end = i;
856
857 while sequence_end < run_length && run.resolved_class(sequence_end) == BidiClass::EuropeanTerminator {
858 sequence_end += 1;
859 }
860
861 if (if sequence_start == 0 { sos } else { run.resolved_class(sequence_start - 1) })
863 == BidiClass::EuropeanNumber
864 || (if sequence_end == run_length { eos } else { run.resolved_class(sequence_end) })
865 == BidiClass::EuropeanNumber
866 {
867 while i < sequence_end {
869 run.set_resolved_class(i, BidiClass::EuropeanNumber);
870 i += 1;
871 }
872 }
873
874 i = sequence_end;
876 i += 1;
877 }
878 }
879
880 if has_es || has_et || has_cs {
882 for i in 0..run_length {
883 match run.resolved_class(i) {
884 BidiClass::EuropeanSeparator | BidiClass::EuropeanTerminator | BidiClass::CommonSeparator => {
885 run.set_resolved_class(i, BidiClass::OtherNeutral);
886 }
887 _ => {}
888 }
889 }
890 }
891
892 if has_en {
894 let mut previous_strong_class = sos;
895
896 for i in 0..run_length {
897 let resolved_class = run.resolved_class(i);
898
899 match resolved_class {
900 BidiClass::EuropeanNumber => {
901 if previous_strong_class == BidiClass::LeftToRight {
903 run.set_resolved_class(i, BidiClass::LeftToRight);
904 }
905 }
906
907 BidiClass::LeftToRight | BidiClass::RightToLeft => {
908 previous_strong_class = resolved_class;
910 }
911 _ => {}
912 }
913 }
914 }
915
916 if has_brackets {
918 run.locate_paired_brackets(&mut self.pending_opening_brackets, &mut self.paired_brackets);
919
920 for i in 0..self.paired_brackets.len() {
921 let paired_bracket = self.paired_brackets[i];
922 let mut strong_direction = run.inspect_paired_bracket(paired_bracket);
923
924 if strong_direction == BidiClass::OtherNeutral {
926 continue;
927 }
928
929 if (strong_direction == BidiClass::LeftToRight || strong_direction == BidiClass::RightToLeft)
931 && strong_direction == run.direction
932 {
933 run.set_paired_bracket_direction(paired_bracket, strong_direction);
934 continue;
935 }
936
937 strong_direction = run.inspect_before_paired_bracket(paired_bracket, sos);
939 if strong_direction == run.direction || strong_direction == BidiClass::OtherNeutral {
940 strong_direction = run.direction;
941 }
942
943 run.set_paired_bracket_direction(paired_bracket, strong_direction);
944 }
945 }
946
947 let mut i = 0;
949 while i < run_length {
950 let resolved_class = run.resolved_class(i);
951
952 if is_neutral_class(resolved_class) {
953 let seq_start = i;
955 let mut seq_end = i;
956
957 while seq_end < run_length && is_neutral_class(run.resolved_class(seq_end)) {
958 seq_end += 1;
959 }
960
961 let class_before = if seq_start == 0 {
963 sos
964 } else {
965 match run.resolved_class(seq_start - 1) {
966 BidiClass::ArabicNumber | BidiClass::EuropeanNumber => BidiClass::RightToLeft,
967 class_before => class_before,
968 }
969 };
970
971 let class_after = if seq_end == run_length {
973 eos
974 } else {
975 match run.resolved_class(seq_end) {
976 BidiClass::ArabicNumber | BidiClass::EuropeanNumber => BidiClass::RightToLeft,
977 class_after => class_after,
978 }
979 };
980
981 let final_resolve_class = if class_before == class_after {
983 class_before
985 } else {
986 run.direction
988 };
989
990 for j in seq_start..seq_end {
992 run.set_resolved_class(j, final_resolve_class);
993 }
994
995 i = seq_end;
997 }
998
999 i += 1;
1000 }
1001
1002 if (run.level & 0x01) == 0 {
1004 for i in 0..run_length {
1006 let resolved_class = run.resolved_class(i);
1007 let current_run_level = run.level_mut(i);
1008
1009 match resolved_class {
1010 BidiClass::RightToLeft => {
1011 *current_run_level = current_run_level.wrapping_add(1);
1012 }
1013 BidiClass::ArabicNumber | BidiClass::EuropeanNumber => {
1014 *current_run_level = current_run_level.wrapping_add(2);
1015 }
1016 _ => {}
1017 }
1018 }
1019 } else {
1020 for i in 0..run_length {
1022 let resolved_class = run.resolved_class(i);
1023 let current_run_level = run.level_mut(i);
1024
1025 if resolved_class != BidiClass::RightToLeft {
1026 *current_run_level = current_run_level.wrapping_add(1);
1027 }
1028 }
1029 }
1030 }
1031
1032 fn reset_whitespace_levels(&self, original_classes: &[BidiClass], resolved_levels: &mut [i8]) {
1034 for i in 0..resolved_levels.len() {
1035 let original_class = original_classes[i];
1036
1037 match original_class {
1038 BidiClass::ParagraphSeparator | BidiClass::SegmentSeparator => {
1039 resolved_levels[i] = self.paragraph_embedding_level;
1041
1042 for j in (0..i).rev() {
1044 if is_whitespace(original_classes[j]) {
1045 resolved_levels[j] = self.paragraph_embedding_level;
1047 } else {
1048 break;
1049 }
1050 }
1051 }
1052 _ => {}
1053 }
1054 }
1055
1056 for j in (0..resolved_levels.len()).rev() {
1058 if is_whitespace(original_classes[j]) {
1059 resolved_levels[j] = self.paragraph_embedding_level;
1061 } else {
1062 break;
1063 }
1064 }
1065 }
1066
1067 fn assign_levels_to_code_points_removed_by_x9(&mut self, original_classes: &[BidiClass], resolved_levels: &mut [i8]) {
1072 if !self.has_isolates && !self.has_embeddings {
1074 return;
1075 }
1076
1077 if self.working_classes.is_empty() {
1079 return;
1080 }
1081
1082 if resolved_levels[0] < 0 {
1084 resolved_levels[0] = self.paragraph_embedding_level;
1085 }
1086
1087 if is_removed_by_x9(original_classes[0]) {
1088 self.working_classes[0] = original_classes[0];
1089 }
1090
1091 for i in 1..self.working_classes.len() {
1092 let original_class = original_classes[i];
1093
1094 if is_removed_by_x9(original_class) {
1095 self.working_classes[i] = original_class;
1096 resolved_levels[i] = resolved_levels[i - 1];
1097 }
1098 }
1099 }
1100
1101 pub fn reset(&mut self) {
1103 if self.has_clean_state {
1104 return;
1105 }
1106
1107 self.has_brackets = false;
1108 self.has_embeddings = false;
1109 self.has_isolates = false;
1110
1111 if self.isolate_pairs.capacity().saturating_mul(std::mem::size_of::<(usize, usize)>()) > 1024 * 1024 {
1113 self.isolate_pairs = HashMap::new();
1114 } else {
1115 self.isolate_pairs.clear();
1116 }
1117
1118 clear_then_reset_if_too_large(&mut self.working_classes);
1119 clear_then_reset_if_too_large(&mut self.resolved_levels);
1120 self.paragraph_embedding_level = 0;
1121 clear_then_reset_if_too_large(&mut self.status_stack);
1122 clear_then_reset_if_too_large(&mut self.x9_map);
1123 clear_then_reset_if_too_large(&mut self.level_runs);
1124 clear_then_reset_if_too_large(&mut self.isolated_run_mapping);
1125 clear_then_reset_if_too_large(&mut self.pending_isolate_openings);
1126 clear_then_reset_if_too_large(&mut self.pending_opening_brackets);
1127 clear_then_reset_if_too_large(&mut self.paired_brackets);
1128
1129 self.has_clean_state = true;
1130 }
1131}
1132
1133struct IsolatedRun<'a> {
1137 map: &'a [usize],
1139
1140 resolved_classes: &'a mut [BidiClass],
1142
1143 original_classes: &'a mut [BidiClass],
1145
1146 levels: &'a mut [i8],
1148
1149 paired_bracket_types: &'a [BidiPairedBracketType],
1151
1152 paired_bracket_values: &'a [i32],
1154
1155 level: i32,
1157
1158 direction: BidiClass,
1160
1161 length: usize,
1163}
1164
1165impl IsolatedRun<'_> {
1166 #[inline(always)]
1167 fn resolved_class(&self, index: usize) -> BidiClass {
1168 self.resolved_classes[self.map[index]]
1169 }
1170
1171 #[inline(always)]
1172 fn set_resolved_class(&mut self, index: usize, value: BidiClass) {
1173 self.resolved_classes[self.map[index]] = value;
1174 }
1175
1176 #[inline(always)]
1177 fn original_class(&self, index: usize) -> BidiClass {
1178 self.original_classes[self.map[index]]
1179 }
1180
1181 #[inline(always)]
1182 fn set_original_class(&mut self, index: usize, value: BidiClass) {
1183 self.original_classes[self.map[index]] = value;
1184 }
1185
1186 #[inline(always)]
1187 fn level_mut(&mut self, index: usize) -> &mut i8 {
1188 &mut self.levels[self.map[index]]
1189 }
1190
1191 #[inline(always)]
1192 fn paired_bracket_type(&self, index: usize) -> BidiPairedBracketType {
1193 self.paired_bracket_types[self.map[index]]
1194 }
1195
1196 #[inline(always)]
1197 fn paired_bracket_value(&self, index: usize) -> i32 {
1198 self.paired_bracket_values[self.map[index]]
1199 }
1200
1201 fn locate_paired_brackets(&self, pending_opening_brackets: &mut Vec<usize>, paired_brackets: &mut Vec<BracketPair>) {
1205 pending_opening_brackets.clear();
1207 paired_brackets.clear();
1208
1209 const SORT_LIMIT: usize = 8;
1216
1217 for i in 0..self.length {
1219 if self.resolved_class(i) != BidiClass::OtherNeutral {
1221 continue;
1222 }
1223
1224 match self.paired_bracket_type(i) {
1225 BidiPairedBracketType::Open => {
1226 if pending_opening_brackets.len() == MAX_PAIRED_BRACKET_DEPTH {
1227 break;
1228 }
1229
1230 pending_opening_brackets.insert(0, i);
1231 }
1232
1233 BidiPairedBracketType::Close => {
1234 for j in 0..pending_opening_brackets.len() {
1236 if self.paired_bracket_value(i) != self.paired_bracket_value(pending_opening_brackets[j]) {
1237 continue;
1238 }
1239
1240 let opener = pending_opening_brackets[j];
1242 if paired_brackets.len() < SORT_LIMIT {
1243 let mut ppi = 0;
1244 while ppi < paired_brackets.len() && paired_brackets[ppi].opening_index < opener {
1245 ppi += 1;
1246 }
1247
1248 paired_brackets.insert(ppi, BracketPair::new(opener, i));
1249 } else {
1250 paired_brackets.push(BracketPair::new(opener, i));
1251 }
1252
1253 pending_opening_brackets.drain(0..=j);
1255 break;
1256 }
1257 }
1258
1259 BidiPairedBracketType::None => {}
1260 }
1261 }
1262
1263 if paired_brackets.len() > SORT_LIMIT {
1265 paired_brackets.sort_unstable_by_key(|pair| pair.opening_index);
1266 }
1267 }
1268
1269 fn inspect_paired_bracket(&self, bracket_pair: BracketPair) -> BidiClass {
1275 let direction_from_level = direction_from_level(self.level);
1276 let mut direction_opposite = BidiClass::OtherNeutral;
1277 for i in bracket_pair.opening_index + 1..bracket_pair.closing_index {
1278 let dir = get_strong_class_n0(self.resolved_class(i));
1279 if dir == BidiClass::OtherNeutral {
1280 continue;
1281 }
1282
1283 if dir == direction_from_level {
1284 return dir;
1285 }
1286
1287 direction_opposite = dir;
1288 }
1289
1290 direction_opposite
1291 }
1292
1293 fn inspect_before_paired_bracket(&self, bracket_pair: BracketPair, sos: BidiClass) -> BidiClass {
1300 for i in (0..bracket_pair.opening_index).rev() {
1301 let direction = get_strong_class_n0(self.resolved_class(i));
1302 if direction != BidiClass::OtherNeutral {
1303 return direction;
1304 }
1305 }
1306
1307 sos
1308 }
1309
1310 fn set_paired_bracket_direction(&mut self, paired_bracket: BracketPair, direction: BidiClass) {
1316 self.set_resolved_class(paired_bracket.opening_index, direction);
1318 self.set_resolved_class(paired_bracket.closing_index, direction);
1319
1320 for i in paired_bracket.opening_index + 1..paired_bracket.closing_index {
1324 if self.original_class(i) == BidiClass::NonspacingMark {
1325 self.set_original_class(i, direction);
1326 } else if self.original_class(i) != BidiClass::BoundaryNeutral {
1327 break;
1328 }
1329 }
1330
1331 for i in paired_bracket.closing_index + 1..self.length {
1333 if self.original_class(i) == BidiClass::NonspacingMark {
1334 self.set_original_class(i, direction);
1335 } else if self.original_class(i) != BidiClass::BoundaryNeutral {
1336 break;
1337 }
1338 }
1339 }
1340}
1341
1342#[inline(always)]
1343fn is_isolate_start(class: BidiClass) -> bool {
1344 const MASK: u32 = (1u32 << BidiClass::LeftToRightIsolate as i32)
1345 | (1u32 << BidiClass::RightToLeftIsolate as i32)
1346 | (1u32 << BidiClass::FirstStrongIsolate as i32);
1347 ((1u32 << class as i32) & MASK) != 0
1348}
1349
1350#[inline(always)]
1352fn is_whitespace(bi_di_class: BidiClass) -> bool {
1353 const MASK: u32 = (1u32 << BidiClass::LeftToRightEmbedding as i32)
1354 | (1u32 << BidiClass::RightToLeftEmbedding as i32)
1355 | (1u32 << BidiClass::LeftToRightOverride as i32)
1356 | (1u32 << BidiClass::RightToLeftOverride as i32)
1357 | (1u32 << BidiClass::PopDirectionalFormat as i32)
1358 | (1u32 << BidiClass::LeftToRightIsolate as i32)
1359 | (1u32 << BidiClass::RightToLeftIsolate as i32)
1360 | (1u32 << BidiClass::FirstStrongIsolate as i32)
1361 | (1u32 << BidiClass::PopDirectionalIsolate as i32)
1362 | (1u32 << BidiClass::BoundaryNeutral as i32)
1363 | (1u32 << BidiClass::WhiteSpace as i32);
1364 ((1u32 << bi_di_class as i32) & MASK) != 0
1365}
1366
1367#[inline(always)]
1374fn direction_from_level(level: i32) -> BidiClass {
1375 if (level & 0x1) == 0 {
1376 BidiClass::LeftToRight
1377 } else {
1378 BidiClass::RightToLeft
1379 }
1380}
1381
1382#[inline(always)]
1388fn is_removed_by_x9(bi_di_class: BidiClass) -> bool {
1389 const MASK: u32 = (1u32 << BidiClass::LeftToRightEmbedding as i32)
1390 | (1u32 << BidiClass::RightToLeftEmbedding as i32)
1391 | (1u32 << BidiClass::LeftToRightOverride as i32)
1392 | (1u32 << BidiClass::RightToLeftOverride as i32)
1393 | (1u32 << BidiClass::PopDirectionalFormat as i32)
1394 | (1u32 << BidiClass::BoundaryNeutral as i32);
1395 ((1u32 << bi_di_class as i32) & MASK) != 0
1396}
1397
1398#[inline(always)]
1400fn is_neutral_class(direction: BidiClass) -> bool {
1401 const MASK: u32 = (1u32 << BidiClass::ParagraphSeparator as i32)
1402 | (1u32 << BidiClass::SegmentSeparator as i32)
1403 | (1u32 << BidiClass::WhiteSpace as i32)
1404 | (1u32 << BidiClass::OtherNeutral as i32)
1405 | (1u32 << BidiClass::RightToLeftIsolate as i32)
1406 | (1u32 << BidiClass::LeftToRightIsolate as i32)
1407 | (1u32 << BidiClass::FirstStrongIsolate as i32)
1408 | (1u32 << BidiClass::PopDirectionalIsolate as i32);
1409 ((1u32 << direction as i32) & MASK) != 0
1410}
1411
1412#[inline(always)]
1418fn get_strong_class_n0(direction: BidiClass) -> BidiClass {
1419 match direction {
1420 BidiClass::EuropeanNumber | BidiClass::ArabicNumber | BidiClass::ArabicLetter | BidiClass::RightToLeft => {
1421 BidiClass::RightToLeft
1422 }
1423 BidiClass::LeftToRight => BidiClass::LeftToRight,
1424 _ => BidiClass::OtherNeutral,
1425 }
1426}
1427
1428#[derive(Clone, Copy, Debug)]
1430struct BracketPair {
1431 opening_index: usize,
1433
1434 closing_index: usize,
1436}
1437
1438impl BracketPair {
1439 #[inline]
1444 fn new(opening_index: usize, closing_index: usize) -> Self {
1445 Self { opening_index, closing_index }
1446 }
1447}
1448
1449#[derive(Clone, Copy, Debug)]
1452struct Status {
1453 embedding_level: i8,
1454 override_status: BidiClass,
1455 isolate_status: bool,
1456}
1457
1458impl Status {
1459 #[inline]
1460 fn new(embedding_level: i8, override_status: BidiClass, isolate_status: bool) -> Self {
1461 Self { embedding_level, override_status, isolate_status }
1462 }
1463}
1464
1465#[derive(Clone, Copy, Debug)]
1468struct LevelRun {
1469 start: usize,
1470 length: usize,
1471 level: i32,
1472 sos: BidiClass,
1473 eos: BidiClass,
1474}
1475
1476impl LevelRun {
1477 #[inline]
1478 fn new(start: usize, length: usize, level: i32, sos: BidiClass, eos: BidiClass) -> Self {
1479 Self { start, length, level, sos, eos }
1480 }
1481}