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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
use crate::tokenizer::Event;
/// To do: could we do without `HashMap`, so we don’t need `std`?
use std::collections::HashMap;
pub fn shift_links(events: &mut [Event], jumps: &[(usize, isize)]) {
let map = |before| {
let mut jump_index = 0;
let mut jump = 0;
while jump_index < jumps.len() {
if jumps[jump_index].0 > before {
break;
}
jump = jumps[jump_index].1;
jump_index += 1;
}
#[allow(clippy::pedantic)]
let next_i = (before as isize) + jump;
assert!(next_i >= 0, "cannot shift before `0`");
#[allow(clippy::pedantic)]
let next = next_i as usize;
next
};
let mut index = 0;
while index < events.len() {
let event = &mut events[index];
event.previous = event.previous.map(map);
event.next = event.next.map(map);
index += 1;
}
}
/// Make it easy to insert and remove things while being performant and keeping
/// links in check.
pub struct EditMap {
consumed: bool,
map: HashMap<usize, (usize, Vec<Event>)>,
}
impl EditMap {
/// Create a new edit map.
pub fn new() -> EditMap {
EditMap {
consumed: false,
map: HashMap::new(),
}
}
/// Create an edit: a remove and/or add at a certain place.
pub fn add(&mut self, index: usize, mut remove: usize, mut add: Vec<Event>) {
assert!(!self.consumed, "cannot add after consuming");
if let Some((curr_remove, mut curr_add)) = self.map.remove(&index) {
remove += curr_remove;
curr_add.append(&mut add);
add = curr_add;
}
self.map.insert(index, (remove, add));
}
/// Done, change the events.
pub fn consume(&mut self, events: &mut [Event]) -> Vec<Event> {
let mut indices: Vec<&usize> = self.map.keys().collect();
let mut next_events: Vec<Event> = vec![];
let mut start = 0;
assert!(!self.consumed, "cannot consume after consuming");
self.consumed = true;
let mut index = 0;
while index < events.len() {
let event = &events[index];
println!(
"ev: {:?} {:?} {:?} {:?} {:?} {:?}",
index,
event.event_type,
event.token_type,
event.content_type,
event.previous,
event.next
);
index += 1;
}
indices.sort_unstable();
let mut jumps: Vec<(usize, isize)> = vec![];
let mut index_into_indices = 0;
let mut shift: isize = 0;
while index_into_indices < indices.len() {
let index = *indices[index_into_indices];
let edit = self.map.get(&index).unwrap();
println!("?? {:?} {:?} {:?}", shift, edit.1.len(), edit.0);
#[allow(clippy::pedantic)]
let next = shift + (edit.1.len() as isize) - (edit.0 as isize);
shift = next;
jumps.push((index, shift));
index_into_indices += 1;
}
let mut index_into_indices = 0;
while index_into_indices < indices.len() {
let index = *indices[index_into_indices];
if start < index {
let append = &mut events[start..index].to_vec();
shift_links(append, &jumps);
next_events.append(append);
}
let (remove, add) = self.map.get(&index).unwrap();
if !add.is_empty() {
let append = &mut add.clone();
let mut index = 0;
while index < append.len() {
let event = &mut append[index];
assert!(event.previous.is_none(), "to do?");
assert!(event.next.is_none(), "to do?");
index += 1;
}
next_events.append(append);
}
start = index + remove;
index_into_indices += 1;
}
if start < events.len() {
next_events.append(&mut events[start..].to_vec());
}
next_events
}
}
|