use icu_segmenter::{
LineSegmenter,
options::{LineBreakOptions, LineBreakStrictness},
};
use super::ascii_breaks;
use crate::line_breaker::{BreakKind, BreakOpportunity};
const CLASSES: &[u8] = b"aZ0 \t\n\r\x0b\x01!\"($%)},-./|?':[+";
fn segmented(text: &[u8], strictness: LineBreakStrictness) -> Vec<BreakOpportunity> {
let mut options = LineBreakOptions::default();
options.strictness = Some(strictness);
let text = std::str::from_utf8(text).expect("ASCII");
LineSegmenter::new_for_non_complex_scripts(options)
.segment_str(text)
.filter(|&offset| offset > 0)
.map(|offset| BreakOpportunity {
offset,
kind: if matches!(text.as_bytes()[offset - 1], b'\n' | b'\r' | 0x0B | 0x0C) {
BreakKind::Hard
} else {
BreakKind::Soft
},
})
.collect()
}
fn assert_breaks_as_segmented(text: &[u8], breaks: &mut Vec<BreakOpportunity>) {
ascii_breaks(text, breaks);
for strictness in [
LineBreakStrictness::Loose,
LineBreakStrictness::Normal,
LineBreakStrictness::Strict,
] {
assert_eq!(
*breaks,
segmented(text, strictness),
"{:?} at {strictness:?}",
String::from_utf8_lossy(text)
);
}
}
#[test]
fn short_ascii_text_breaks_where_the_segmenter_breaks_it() {
let mut breaks = Vec::new();
for first in 0..=0x7F_u8 {
for second in 0..=0x7F_u8 {
assert_breaks_as_segmented(&[first, second], &mut breaks);
}
}
let mut text = Vec::new();
for length in 1..=4 {
let count = CLASSES.len().pow(length);
for mut index in 0..count {
text.clear();
for _ in 0..length {
text.push(CLASSES[index % CLASSES.len()]);
index /= CLASSES.len();
}
assert_breaks_as_segmented(&text, &mut breaks);
}
}
}
#[test]
fn long_ascii_text_breaks_where_the_segmenter_breaks_it() {
let alphabet = CLASSES;
let mut state = 0x2545_F491_u32;
let mut text = Vec::new();
let mut breaks = Vec::new();
for _ in 0..100_000 {
text.clear();
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;
let length = 5 + state % 20;
for _ in 0..length {
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;
text.push(alphabet[state as usize % alphabet.len()]);
}
assert_breaks_as_segmented(&text, &mut breaks);
}
}