use crate::event::Event;
use alloc::{vec, vec::Vec};
fn shift_links(events: &mut [Event], jumps: &[(usize, usize, usize)]) {
let mut jump_index = 0;
let mut index = 0;
let mut add = 0;
let mut rm = 0;
while index < events.len() {
let rm_curr = rm;
while jump_index < jumps.len() && jumps[jump_index].0 <= index {
add = jumps[jump_index].2;
rm = jumps[jump_index].1;
jump_index += 1;
}
if rm > rm_curr {
index += rm - rm_curr;
} else {
if let Some(link) = &events[index].link {
if let Some(next) = link.next {
events[next].link.as_mut().unwrap().previous = Some(index + add - rm);
while jump_index < jumps.len() && jumps[jump_index].0 <= next {
add = jumps[jump_index].2;
rm = jumps[jump_index].1;
jump_index += 1;
}
events[index].link.as_mut().unwrap().next = Some(next + add - rm);
index = next;
continue;
}
}
index += 1;
}
}
}
#[derive(Debug)]
pub struct EditMap {
map: Vec<(usize, usize, Vec<Event>)>,
}
impl EditMap {
pub fn new() -> EditMap {
EditMap { map: vec![] }
}
pub fn add(&mut self, index: usize, remove: usize, add: Vec<Event>) {
add_impl(self, index, remove, add, false);
}
pub fn add_before(&mut self, index: usize, remove: usize, add: Vec<Event>) {
add_impl(self, index, remove, add, true);
}
pub fn consume(&mut self, events: &mut Vec<Event>) {
self.map
.sort_unstable_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
if self.map.is_empty() {
return;
}
let mut jumps = Vec::with_capacity(self.map.len());
let mut index = 0;
let mut add_acc = 0;
let mut remove_acc = 0;
while index < self.map.len() {
let (at, remove, add) = &self.map[index];
remove_acc += remove;
add_acc += add.len();
jumps.push((*at, remove_acc, add_acc));
index += 1;
}
shift_links(events, &jumps);
let len_before = events.len();
let mut index = self.map.len();
let mut vecs = Vec::with_capacity(index * 2 + 1);
while index > 0 {
index -= 1;
vecs.push(events.split_off(self.map[index].0 + self.map[index].1));
vecs.push(self.map[index].2.split_off(0));
events.truncate(self.map[index].0);
}
vecs.push(events.split_off(0));
events.reserve(len_before + add_acc - remove_acc);
while let Some(mut slice) = vecs.pop() {
events.append(&mut slice);
}
self.map.truncate(0);
}
}
fn add_impl(edit_map: &mut EditMap, at: usize, remove: usize, mut add: Vec<Event>, before: bool) {
let mut index = 0;
if remove == 0 && add.is_empty() {
return;
}
while index < edit_map.map.len() {
if edit_map.map[index].0 == at {
edit_map.map[index].1 += remove;
if before {
add.append(&mut edit_map.map[index].2);
edit_map.map[index].2 = add;
} else {
edit_map.map[index].2.append(&mut add);
}
return;
}
index += 1;
}
edit_map.map.push((at, remove, add));
}