use crate::index::{
config::IndexOrd,
tree::{
ChangeResults, IndexLimits, ParentChange, PosRef,
nodes::TreeNodeRef,
path::{BottomDepth, Path, TopDepth},
},
};
#[derive(Clone)]
pub(crate) struct LockItem<K: Clone> {
path: Path<K>,
len: usize,
add: Option<usize>,
removes: Option<usize>,
check_key: bool,
}
impl<K: IndexOrd + Clone> LockItem<K> {
fn new(path: Path<K>, len: usize) -> Self {
Self {
path,
len,
add: None,
removes: None,
check_key: false,
}
}
fn new_changes(path: Path<K>, len: usize, parent_change: &ParentChange<K>) -> Self {
Self {
path,
len,
add: Some(parent_change.add_count()),
removes: Some(parent_change.remove_count()),
check_key: parent_change.change_prev_key(),
}
}
pub fn merge_v(&mut self, parent_change: &ParentChange<K>, path: Path<K>) {
self.add = Some(self.add.unwrap_or(0) + parent_change.add_count());
self.removes = Some(self.removes.unwrap_or(0) + parent_change.remove_count());
self.check_key |= parent_change.change_prev_key();
self.path = path;
}
pub fn len(&self) -> usize {
let mut len = self.len;
if let Some(a) = self.add {
len += a;
}
if let Some(r) = self.removes {
len -= r;
}
len
}
pub fn parent_id(&self) -> Option<TreeNodeRef> {
self.path
.get(TopDepth(self.path.len() - 2))
.map(|x| x.pos_ref().node_ref)
}
pub fn path(&self) -> &Path<K> {
&self.path
}
pub fn check_key(&self) -> bool {
self.check_key
}
}
pub(crate) struct LockGroup<K: Clone> {
depth: BottomDepth,
group: Vec<LockItem<K>>,
}
impl<K: IndexOrd + Clone> LockGroup<K> {
pub(crate) fn new(depth: BottomDepth) -> Self {
Self {
depth,
group: Vec::new(),
}
}
pub(crate) fn is_for(&self, node_ref: &TreeNodeRef) -> bool {
self.group.is_empty()
|| self
.group
.iter()
.rfind(|e| e.path.last_id() == Some(*node_ref))
.is_some()
}
pub(crate) fn add(&mut self, mut path: Path<K>, len: usize, pc: &Option<&ParentChange<K>>) {
path.compute_depths_start(self.depth);
for g in &mut self.group {
if g.path.point_same_node(&path) {
if let Some(parent_change) = pc {
if parent_change.path().point_same_node(&path) {
g.merge_v(parent_change, path);
}
}
return;
}
}
if let Some(parent_change) = pc {
if parent_change.path().point_same_node(&path) {
self.group.push(LockItem::new_changes(path, len, parent_change));
} else {
self.group.push(LockItem::new(path, len));
}
} else {
self.group.push(LockItem::new(path, len));
}
}
fn set_change(&mut self, nr: &TreeNodeRef, cr: ChangeResults) {
let mut found = false;
for g in &mut self.group {
if g.path.last_pos_ref().map(|r| &r.node_ref) == Some(nr) {
if let Some(nadd) = cr.add {
g.add = Some(if let Some(add) = g.add { add + nadd } else { nadd });
}
if let Some(nrem) = cr.remove {
g.removes = Some(if let Some(r) = g.removes { r + nrem } else { nrem });
}
found = true;
break;
}
}
assert!(found);
}
pub(crate) fn parent_group(&self, limits: &IndexLimits) -> Vec<ParentChange<K>> {
let mut parents = Vec::new();
let mut parent_change: Option<ParentChange<K>> = None;
for value in &self.group {
parent_change = Some(if let Some(mut pc) = parent_change {
if pc.id() == value.parent_id().unwrap() {
pc.add_child(value, limits);
pc
} else {
if !pc.children().is_empty() {
parents.push(pc);
}
ParentChange::new_child(value, limits)
}
} else {
ParentChange::new_child(value, limits)
});
}
if let Some(x) = parent_change {
if !x.children().is_empty() {
parents.push(x);
}
}
parents
}
pub fn is_not_only_root(&self) -> bool {
self.group[0].path.len() > 1
}
pub fn is_only_root(&self) -> bool {
self.group[0].path.len() == 1
}
}
pub(crate) struct LockGroups<K: Clone> {
groups: Vec<LockGroup<K>>,
last: Option<LockGroup<K>>,
}
impl<K: Clone + IndexOrd> LockGroups<K> {
pub(crate) fn new() -> Self {
Self {
groups: Default::default(),
last: Default::default(),
}
}
pub(crate) fn group_for_id(&mut self, pos_ref: &PosRef<K>, bottom_depth: BottomDepth) -> &mut LockGroup<K> {
let lock_group = if let Some(lg) = self.last.take() {
if lg.is_for(&pos_ref.node_ref) {
lg
} else {
if !lg.group.is_empty() {
self.groups.push(lg);
}
LockGroup::new(bottom_depth)
}
} else {
LockGroup::new(bottom_depth)
};
self.last = Some(lock_group);
self.last.as_mut().unwrap()
}
pub(crate) fn last_set_change(&mut self, nr: &TreeNodeRef, cr: ChangeResults) {
self.last.as_mut().unwrap().set_change(nr, cr)
}
pub(crate) fn finish(&mut self) {
if let Some(lg) = self.last.take() {
if !lg.group.is_empty() {
self.groups.push(lg);
}
}
}
pub(crate) fn groups(self) -> Vec<LockGroup<K>> {
self.groups
}
}