1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use crate::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Segment<'a> {
Plain { text: &'a str },
Rubied { text: &'a str, ruby: &'a str },
}
impl<'a> Segment<'a> {
pub fn plain_text(&self) -> &'a str {
match *self {
Segment::Plain { text } => text,
Segment::Rubied { text, .. } => text,
}
}
pub fn to_interlinear_encoding(&self) -> String {
match *self {
Segment::Plain { text } => text.into(),
Segment::Rubied { text, ruby } => format!("\u{FFF9}{}\u{FFFA}{}\u{FFFB}", text, ruby),
}
}
}
#[derive(Clone)]
pub struct SegmentIterator<'a> {
pub(crate) string: &'a RubyString,
pub(crate) next_text_start: usize,
pub(crate) next_placement_idx: usize,
}
impl<'a> Iterator for SegmentIterator<'a> {
type Item = Segment<'a>;
fn next(&mut self) -> Option<Segment<'a>> {
if self.next_text_start >= self.string.packed_text.len() {
return None;
}
if self.next_placement_idx >= self.string.placements.len() {
let text_end = self.string.packed_text.len();
let text = &self.string.packed_text[self.next_text_start..text_end];
self.next_text_start = text_end;
return Some(Segment::Plain { text });
}
let placement = self.string.placements[self.next_placement_idx];
if self.next_text_start < placement.text_start {
let text = &self.string.packed_text[self.next_text_start..placement.text_start];
self.next_text_start = placement.text_start;
Some(Segment::Plain { text })
} else {
let text = &self.string.packed_text[placement.text_start..placement.text_end];
let ruby = &self.string.packed_ruby[placement.ruby_start..placement.ruby_end];
self.next_text_start = placement.text_end;
self.next_placement_idx += 1;
Some(Segment::Rubied { text, ruby })
}
}
}