Skip to content

Commit 032f8cc

Browse files
committed
[lib] Impl BidiInfo.reordered_levels_per_char()
This allows easier testing of the logic, specially having specific cases from the conformance test as unit test, as corner bugs unfold.
1 parent cf1b01e commit 032f8cc

File tree

3 files changed

+79
-12
lines changed

3 files changed

+79
-12
lines changed

src/implicit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [B
2626
// by an "earlier" rule. We should either split this into separate passes, or preserve
2727
// extra state so each rule can see the correct previous class.
2828

29+
// FIXME: Also, this could be the cause of increased failure for using longer-UTF-8 chars in
30+
// conformance tests, like BidiTest:69635 (AL ET EN)
31+
2932
let mut prev_class = sequence.sos;
3033
let mut last_strong_is_al = false;
3134
let mut et_run_indices = Vec::new(); // for W5

src/lib.rs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,25 @@ impl<'text> BidiInfo<'text> {
291291
}
292292
}
293293

294-
/// Re-order a line based on resolved levels and return only the embedding levels.
294+
/// Re-order a line based on resolved levels and return only the embedding levels, one `Level`
295+
/// per *byte*.
295296
pub fn reordered_levels(&self, para: &ParagraphInfo, line: Range<usize>) -> Vec<Level> {
296297
let (levels, _) = self.visual_runs(para, line.clone());
297298
levels
298299
}
299300

301+
/// Re-order a line based on resolved levels and return only the embedding levels, one `Level`
302+
/// per *character*.
303+
pub fn reordered_levels_per_char(
304+
&self,
305+
para: &ParagraphInfo,
306+
line: Range<usize>,
307+
) -> Vec<Level> {
308+
let levels = self.reordered_levels(para, line);
309+
self.text.char_indices().map(|(i, _)| levels[i]).collect()
310+
}
311+
312+
300313
/// Re-order a line based on resolved levels and return the line in display order.
301314
pub fn reorder_line(&self, para: &ParagraphInfo, line: Range<usize>) -> Cow<'text, str> {
302315
let (levels, runs) = self.visual_runs(para, line.clone());
@@ -637,6 +650,10 @@ mod tests {
637650
],
638651
}
639652
);
653+
654+
/// BidiTest:69635 (AL ET EN)
655+
let bidi_info = BidiInfo::new("\u{060B}\u{20CF}\u{06F9}", None);
656+
assert_eq!(bidi_info.original_classes, vec![AL, AL, ET, ET, ET, EN, EN]);
640657
}
641658

642659
#[test]
@@ -754,6 +771,60 @@ mod tests {
754771
vec!["ef].)gh&[דג(בא"]
755772
);
756773
}
774+
775+
fn reordered_levels_for_paras(text: &str) -> Vec<Vec<Level>> {
776+
let bidi_info = BidiInfo::new(text, None);
777+
bidi_info
778+
.paragraphs
779+
.iter()
780+
.map(|para| bidi_info.reordered_levels(para, para.range.clone()))
781+
.collect()
782+
}
783+
784+
fn reordered_levels_per_char_for_paras(text: &str) -> Vec<Vec<Level>> {
785+
let bidi_info = BidiInfo::new(text, None);
786+
bidi_info
787+
.paragraphs
788+
.iter()
789+
.map(|para| bidi_info.reordered_levels_per_char(para, para.range.clone()))
790+
.collect()
791+
}
792+
793+
#[test]
794+
fn test_reordered_levels() {
795+
796+
/// BidiTest:946 (LRI PDI)
797+
let text = "\u{2067}\u{2069}";
798+
assert_eq!(
799+
reordered_levels_for_paras(text),
800+
vec![Level::vec(&[0, 0, 0, 0, 0, 0])]
801+
);
802+
assert_eq!(
803+
reordered_levels_per_char_for_paras(text),
804+
vec![Level::vec(&[0, 0])]
805+
);
806+
807+
/* TODO
808+
/// BidiTest:69635 (AL ET EN)
809+
let text = "\u{060B}\u{20CF}\u{06F9}";
810+
assert_eq!(
811+
reordered_levels_for_paras(text),
812+
vec![Level::vec(&[1, 1, 1, 1, 1, 2, 2])]
813+
);
814+
assert_eq!(
815+
reordered_levels_per_char_for_paras(text),
816+
vec![Level::vec(&[1, 1, 2])]
817+
);
818+
*/
819+
820+
/* TODO
821+
// BidiTest:291284 (AN RLI PDF R)
822+
assert_eq!(
823+
reordered_levels_per_char_for_paras("\u{0605}\u{2067}\u{202C}\u{0590}"),
824+
vec![&["2", "0", "x", "1"]]
825+
);
826+
*/
827+
}
757828
}
758829

759830

tests/conformance_tests.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ fn test_basic_conformance() {
8484

8585
// Check levels
8686
let exp_levels: Vec<String> = exp_levels.iter().map(|x| x.to_owned()).collect();
87-
let levels = gen_levels_list_from_bidi_info(&input_string, &bidi_info);
87+
let para = &bidi_info.paragraphs[0];
88+
let levels = bidi_info.reordered_levels_per_char(para, para.range.clone());
8889
if levels != exp_levels {
8990
fails.push(
9091
Fail {
@@ -181,7 +182,8 @@ fn test_character_conformance() {
181182
let bidi_info = BidiInfo::new(&input_string, input_base_level);
182183

183184
// Check levels
184-
let levels = gen_levels_list_from_bidi_info(&input_string, &bidi_info);
185+
let para = &bidi_info.paragraphs[0];
186+
let levels = bidi_info.reordered_levels_per_char(para, para.range.clone());
185187
if levels != exp_levels {
186188
fails.push(
187189
Fail {
@@ -236,22 +238,13 @@ fn gen_base_level_for_characters_tests(idx: usize) -> Option<Level> {
236238
}
237239

238240

239-
/// We need to collaps levels to one-per-character from one-per-byte format.
240-
fn gen_levels_list_from_bidi_info(input_str: &str, bidi_info: &BidiInfo) -> Vec<Level> {
241-
let para = &bidi_info.paragraphs[0];
242-
let levels = bidi_info.reordered_levels(para, para.range.clone());
243-
// TODO: Move to impl BidiInfo as pub api
244-
input_str.char_indices().map(|(i, _)| levels[i]).collect()
245-
}
246-
247241
fn get_sample_string_from_bidi_classes(class_names: &[&str]) -> String {
248242
class_names
249243
.iter()
250244
.map(|class_name| gen_char_from_bidi_class(class_name))
251245
.collect()
252246
}
253247

254-
/// TODO: Auto-gen in tables.rs ?
255248
fn gen_char_from_bidi_class(class_name: &str) -> char {
256249
match class_name {
257250
"AL" => '\u{060B}',

0 commit comments

Comments
 (0)