use std::fmt::Debug;
use eyre::bail;
use indexset::cdc::change::ChangeEvent;
use indexset::core::pair::Pair;
use rkyv::de::Pool;
use rkyv::rancor::Strategy;
use rkyv::ser::allocator::ArenaHandle;
use rkyv::ser::sharing::Share;
use rkyv::ser::Serializer;
use rkyv::util::AlignedVec;
use rkyv::{Archive, Deserialize, Serialize};
use crate::{IndexPage, IndexValue, Link, SizeMeasurable};
impl<T: Default + SizeMeasurable> IndexPage<T>
where
T: Archive
+ Debug
+ Clone
+ for<'a> Serialize<
Strategy<Serializer<AlignedVec, ArenaHandle<'a>, Share>, rkyv::rancor::Error>,
> + PartialEq
+ PartialOrd
+ Ord
+ Send
+ Sync,
<T as Archive>::Archived: Deserialize<T, Strategy<Pool, rkyv::rancor::Error>>
+ Ord
+ Eq
+ PartialEq
+ PartialOrd
+ Debug,
{
pub fn apply_change_event(&mut self, event: ChangeEvent<Pair<T, Link>>) -> eyre::Result<()> {
match event.clone() {
ChangeEvent::InsertAt {
event_id: _,
max_value: _,
value,
index,
} => {
if value.key > self.node_id.key {
self.node_id = value.clone().into();
}
if index == self.current_length as usize && value.key == self.node_id.key {
self.node_id = value.clone().into();
}
self.apply_insert_at(index, value)?;
Ok(())
}
ChangeEvent::RemoveAt {
event_id: _,
max_value,
value,
index,
} => {
if max_value == value && index != 0 {
let previous_value_pos = self.slots[index - 1];
let value = &self.index_values[previous_value_pos as usize];
self.node_id = value.clone();
}
self.apply_remove_at(index)?;
Ok(())
}
ChangeEvent::SplitNode { .. }
| ChangeEvent::CreateNode { .. }
| ChangeEvent::RemoveNode { .. } => {
bail!("Events of `SplitNode`, `CreateNode` or `RemoveNode` can not be applied")
}
}
}
fn apply_insert_at(&mut self, index: usize, value: Pair<T, Link>) -> eyre::Result<()> {
self.slots.insert(index, self.current_index);
self.slots.remove(self.size as usize);
self.current_length += 1;
let index_value = IndexValue {
key: value.key.clone(),
link: value.value,
};
let mut value_position = self.current_index;
self.index_values[value_position as usize] = index_value;
if value_position != self.size - 1 {
value_position += 1;
let mut value = &self.index_values[value_position as usize];
while value != &IndexValue::default() && value_position != self.size - 1 {
value_position += 1;
value = &self.index_values[value_position as usize];
}
self.current_index = value_position;
}
Ok(())
}
fn apply_remove_at(&mut self, index: usize) -> eyre::Result<()> {
let value_position = self.slots.remove(index);
self.slots.push(0);
self.current_length -= 1;
if value_position < self.current_index {
self.current_index = value_position;
}
self.index_values[value_position as usize] = IndexValue::default();
Ok(())
}
}
#[cfg(test)]
mod test {
use crate::{IndexPage, IndexValue, Link};
use indexset::cdc::change::ChangeEvent;
use indexset::core::pair::Pair;
#[test]
fn test_insert_at() {
let mut page = IndexPage::new(
IndexValue {
key: 1,
link: Default::default(),
},
10,
);
let event = ChangeEvent::InsertAt {
event_id: 0.into(),
max_value: Pair {
key: 1,
value: Link::default(),
},
value: Pair {
key: 1,
value: Link::default(),
},
index: 0,
};
page.apply_change_event(event).unwrap();
assert_eq!(page.node_id.key, 1);
assert_eq!(
page.index_values[0],
IndexValue {
key: 1,
link: Link::default(),
}
)
}
#[test]
fn test_insert_at_second() {
let mut page = IndexPage::new(
IndexValue {
key: 1,
link: Default::default(),
},
10,
);
let event = ChangeEvent::InsertAt {
event_id: 0.into(),
max_value: Pair {
key: 1,
value: Link::default(),
},
value: Pair {
key: 1,
value: Link::default(),
},
index: 0,
};
page.apply_change_event(event).unwrap();
let event = ChangeEvent::InsertAt {
event_id: 0.into(),
max_value: Pair {
key: 1,
value: Link::default(),
},
value: Pair {
key: 2,
value: Link::default(),
},
index: 1,
};
page.apply_change_event(event).unwrap();
assert_eq!(page.node_id.key, 2);
assert_eq!(
page.index_values[0],
IndexValue {
key: 1,
link: Link::default(),
}
);
assert_eq!(
page.index_values[1],
IndexValue {
key: 2,
link: Link::default(),
}
)
}
#[test]
fn test_remove_at() {
let mut page = IndexPage::new(
IndexValue {
key: 1,
link: Default::default(),
},
10,
);
let event = ChangeEvent::InsertAt {
event_id: 0.into(),
max_value: Pair {
key: 1,
value: Link::default(),
},
value: Pair {
key: 1,
value: Link::default(),
},
index: 0,
};
page.apply_change_event(event).unwrap();
let event = ChangeEvent::InsertAt {
event_id: 0.into(),
max_value: Pair {
key: 1,
value: Link::default(),
},
value: Pair {
key: 2,
value: Link::default(),
},
index: 1,
};
page.apply_change_event(event).unwrap();
let event = ChangeEvent::RemoveAt {
event_id: 0.into(),
max_value: Pair {
key: 2,
value: Link::default(),
},
value: Pair {
key: 1,
value: Link::default(),
},
index: 0,
};
page.apply_change_event(event).unwrap();
assert_eq!(page.node_id.key, 2);
assert_eq!(page.index_values[0], IndexValue::default());
assert_eq!(
page.index_values[1],
IndexValue {
key: 2,
link: Link::default(),
}
)
}
#[test]
fn test_remove_at_node_id() {
let mut page = IndexPage::new(
IndexValue {
key: 1,
link: Default::default(),
},
10,
);
let event = ChangeEvent::InsertAt {
event_id: 0.into(),
max_value: Pair {
key: 1,
value: Link::default(),
},
value: Pair {
key: 1,
value: Link::default(),
},
index: 0,
};
page.apply_change_event(event).unwrap();
let event = ChangeEvent::InsertAt {
event_id: 0.into(),
max_value: Pair {
key: 1,
value: Link::default(),
},
value: Pair {
key: 2,
value: Link::default(),
},
index: 1,
};
page.apply_change_event(event).unwrap();
let event = ChangeEvent::RemoveAt {
event_id: 0.into(),
max_value: Pair {
key: 2,
value: Link::default(),
},
value: Pair {
key: 2,
value: Link::default(),
},
index: 1,
};
page.apply_change_event(event).unwrap();
assert_eq!(page.node_id.key, 1);
assert_eq!(
page.index_values[0],
IndexValue {
key: 1,
link: Link::default(),
}
);
assert_eq!(page.index_values[1], IndexValue::default())
}
}