use std::marker::PhantomData;
use data::{Flow, LinkReference, LinksConstants};
use super::{helpers, macros::forward};
use crate::{
data::{ReadHandler, WriteHandler},
mem::UncheckedMutation,
Doublets, Error, Link, Links,
};
#[derive(Debug)]
pub struct CheckedMutation<'a, T: LinkReference, L: UncheckedMutation<T>> {
links: &'a mut L,
_marker: PhantomData<fn(T)>,
}
impl<'a, T: LinkReference, L: UncheckedMutation<T>> CheckedMutation<'a, T, L> {
#[inline]
pub const fn new(links: &'a mut L) -> Self {
Self {
links,
_marker: PhantomData,
}
}
#[inline]
#[must_use]
pub const fn inner(&self) -> &L {
self.links
}
#[inline]
#[must_use]
pub fn inner_mut(&mut self) -> &mut L {
self.links
}
#[inline]
#[must_use]
pub fn into_inner(self) -> &'a mut L {
self.links
}
}
impl<T: LinkReference, L: UncheckedMutation<T>> Links<T> for CheckedMutation<'_, T, L> {
forward!(count_links, each_links, create_links);
#[inline]
fn update_links(
&mut self,
query: &[T],
change: &[T],
handler: WriteHandler<'_, T>,
) -> Result<Flow, Error<T>> {
let constants = self.links.constants();
let index = helpers::part(query, constants.index_part);
let source = helpers::part(change, constants.source_part);
let target = helpers::part(change, constants.target_part);
self.links.try_get_link(index)?;
Ok(unsafe { self.links.update_unchecked(index, source, target, handler) })
}
#[inline]
fn delete_links(
&mut self,
query: &[T],
handler: WriteHandler<'_, T>,
) -> Result<Flow, Error<T>> {
let index = helpers::part(query, self.links.constants().index_part);
let original = self.links.try_get_link(index)?;
let null = T::from_byte(0);
unsafe {
if original.source != null || original.target != null {
self.links
.update_unchecked(index, null, null, &mut |_, _| Flow::Continue);
}
Ok(self
.links
.release_unchecked(index, &mut |_, after| handler(original.clone(), after)))
}
}
}
impl<T: LinkReference, L: UncheckedMutation<T>> Doublets<T> for CheckedMutation<'_, T, L> {
#[inline]
fn get_link(&self, index: T) -> Option<Link<T>> {
self.links.get_link(index)
}
}