const MAX_PER_RECORD: u32 = 32;
use super::shift_list::{Shift, ShiftList, Shiftable};
#[derive(Default, Clone, Debug)]
pub struct Records(ShiftList<[u32; 3]>);
impl Records {
pub fn new(max: [usize; 3]) -> Self {
Self(ShiftList::new(max.map(|x| x as i32)))
}
pub fn insert(&mut self, new: [usize; 3]) {
if MAX_PER_RECORD * 2 > self.0.max()[0] as u32 {
return;
}
let new = new.map(|x| x as u32);
let i = match self.0.find_by_key(new[0], |[b, ..]| b) {
Ok(_) => return,
Err(i) => {
let next = self.0.get(i);
let prev = i.checked_sub(1).and_then(|prev_i| self.0.get(prev_i));
if next.is_none_or(|[b, ..]| b >= new[0] + MAX_PER_RECORD)
&& prev.is_none_or(|[b, ..]| b + MAX_PER_RECORD <= new[0])
{
i
} else {
return;
}
}
};
self.0.insert(i, new);
}
pub fn transform(&mut self, start: [usize; 3], old_len: [usize; 3], new_len: [usize; 3]) {
let (Ok(s_i) | Err(s_i)) = self.0.find_by_key(start[0] as u32, |[b, ..]| b);
let (Ok(e_i) | Err(e_i)) = self
.0
.find_by_key((start[0] + old_len[0]) as u32, |[b, ..]| b);
self.0
.extract_if_while(s_i..e_i, |_, _| Some(true))
.for_each(|_| {});
self.0.shift_by(
s_i,
[
new_len[0] as i32 - old_len[0] as i32,
new_len[1] as i32 - old_len[1] as i32,
new_len[2] as i32 - old_len[2] as i32,
],
);
}
pub fn max(&self) -> [usize; 3] {
self.0.max().map(|x| x as usize)
}
pub fn closest_to_by_key(&self, key: usize, by: fn([u32; 3]) -> u32) -> [usize; 3] {
let key = key as u32;
match self.0.find_by_key(key, by) {
Ok(i) => self.0.get(i).unwrap().map(|x| x as usize),
Err(i) => {
let prev = i.checked_sub(1).and_then(|prev_i| self.0.get(prev_i));
let next = self.0.get(i);
let (prev, next) = match (prev, next) {
(None, None) => ([0; 3], self.0.max().map(|x| x as u32)),
(None, Some(next)) => ([0; 3], next),
(Some(prev), None) => (prev, self.0.max().map(|x| x as u32)),
(Some(prev), Some(next)) => (prev, next),
};
if key - by(prev) > by(next) - key {
next.map(|x| x as usize)
} else {
prev.map(|x| x as usize)
}
}
}
}
}
impl Shiftable for [u32; 3] {
type Shift = [i32; 3];
fn shift(self, by: Self::Shift) -> Self {
let sh = |i: usize| (self[i] as i32 + by[i]) as u32;
[sh(0), sh(1), sh(2)]
}
}
impl Shift for [i32; 3] {
fn neg(self) -> Self {
[-self[0], -self[1], -self[2]]
}
fn add(self, other: Self) -> Self {
[self[0] + other[0], self[1] + other[1], self[2] + other[2]]
}
}