use std::{any::Any, collections::HashMap, hash::Hash, marker::PhantomData};
use crate::{
backend::{tree, AsElementTag},
error::Error,
};
use tree::ForestTokenAddr;
pub union UnionOption<T> {
none: (),
some: std::mem::ManuallyDrop<T>,
}
impl<T> UnionOption<T> {
#[inline(always)]
pub fn none() -> Self {
Self { none: () }
}
#[inline(always)]
pub fn some(inner: T) -> Self {
Self {
some: std::mem::ManuallyDrop::new(inner),
}
}
#[inline(always)]
pub unsafe fn unwrap_unchecked(self) -> T {
std::mem::ManuallyDrop::into_inner(self.some)
}
#[inline(always)]
pub unsafe fn as_ref_unchecked(&self) -> &T {
&self.some
}
}
pub trait OwnerWeak {
fn apply_updates(&self) -> Result<(), Error>;
fn clone_owner_weak(&self) -> Box<dyn OwnerWeak>;
}
pub struct DynNode {
inner: Box<dyn Any>,
}
impl DynNode {
#[inline(always)]
pub fn new<N: 'static>(n: N) -> Self {
Self { inner: Box::new(n) }
}
#[inline(always)]
pub unsafe fn node_unchecked<N: 'static>(&mut self) -> &mut N {
&mut *(&mut *self.inner as *mut dyn Any as *mut N)
}
#[inline(always)]
pub fn as_mut<N: 'static>(&mut self) -> &mut N {
self.inner.downcast_mut().unwrap()
}
#[inline(always)]
pub fn as_ref<N: 'static>(&self) -> &N {
self.inner.downcast_ref().unwrap()
}
}
pub type DynNodeList = Box<[DynNode]>;
#[derive(Debug)]
pub struct Node<N: AsElementTag> {
pub tag: N::Target,
pub child_nodes: N::SlotChildren,
}
impl<N: AsElementTag> Node<N> {
#[inline(always)]
pub fn new(tag: N::Target, child_nodes: N::SlotChildren) -> Self {
Self { tag, child_nodes }
}
#[inline]
pub fn iter_slots(
&self,
) -> <N::SlotChildren as SlotKindTrait<ForestTokenAddr, DynNodeList>>::Iter<'_> {
self.child_nodes.iter()
}
#[inline]
pub fn single_slot(&self) -> Option<&DynNodeList> {
self.child_nodes.single_slot()
}
}
#[derive(Debug)]
pub struct ControlNode<C> {
pub forest_token: tree::ForestToken,
pub content: C,
}
impl<C> ControlNode<C> {
#[inline(always)]
pub fn new(forest_token: tree::ForestToken, content: C) -> Self {
Self {
forest_token,
content,
}
}
}
pub struct Branch {
pub cur: usize,
pub children: DynNodeList,
}
pub trait SlotKindTrait<K, C>: Default {
type Update<'a>: SlotKindUpdateTrait<'a, K, C>
where
Self: 'a,
K: 'a,
C: 'a;
type Iter<'a>: Iterator<Item = &'a C>
where
Self: 'a,
C: 'a;
fn may_update(&self) -> bool;
#[doc(hidden)]
fn add(&mut self, k: K, c: C) -> Result<(), Error>;
#[doc(hidden)]
fn remove(&mut self, k: K) -> Result<C, Error>;
#[doc(hidden)]
fn get(&self, k: K) -> Result<&C, Error>;
#[doc(hidden)]
fn get_mut(&mut self, k: K) -> Result<&mut C, Error>;
#[doc(hidden)]
fn update<'a>(&'a mut self) -> Self::Update<'a>;
fn iter<'a>(&'a self) -> Self::Iter<'a>;
fn single_slot(&self) -> Option<&C>;
}
pub trait SlotKindUpdateTrait<'a, K: 'a, C: 'a> {
#[doc(hidden)]
fn add(&mut self, k: K, c: C) -> Result<(), Error>;
#[doc(hidden)]
fn reuse(&mut self, k: K) -> Result<&mut C, Error>;
#[doc(hidden)]
fn finish(self, remove_item_fn: impl FnMut(C) -> Result<(), Error>) -> Result<(), Error>;
}
#[derive(Debug)]
pub struct NoneSlot<K, C> {
phantom: PhantomData<(K, C)>,
}
impl<K, C> Default for NoneSlot<K, C> {
#[inline]
fn default() -> Self {
Self {
phantom: PhantomData,
}
}
}
impl<K, C> SlotKindTrait<K, C> for NoneSlot<K, C> {
type Update<'a> = NoneSlotUpdate<'a, K, C> where K: 'a, C: 'a;
type Iter<'a> = std::iter::Empty<&'a C> where K: 'a, C: 'a;
#[inline(always)]
fn may_update(&self) -> bool {
false
}
#[inline]
fn add(&mut self, _: K, _: C) -> Result<(), Error> {
Err(Error::ListChangeWrong)
}
#[inline]
fn remove(&mut self, _: K) -> Result<C, Error> {
Err(Error::ListChangeWrong)
}
#[inline]
fn get(&self, _: K) -> Result<&C, Error> {
Err(Error::ListChangeWrong)
}
#[inline]
fn get_mut(&mut self, _: K) -> Result<&mut C, Error> {
Err(Error::ListChangeWrong)
}
#[inline]
fn update<'a>(&'a mut self) -> Self::Update<'a> {
NoneSlotUpdate {
phantom: PhantomData,
}
}
#[inline]
fn iter(&self) -> Self::Iter<'_> {
std::iter::empty()
}
#[inline]
fn single_slot(&self) -> Option<&C> {
None
}
}
#[doc(hidden)]
pub struct NoneSlotUpdate<'a, K, C> {
phantom: PhantomData<&'a (K, C)>,
}
impl<'a, K: 'a, C: 'a> SlotKindUpdateTrait<'a, K, C> for NoneSlotUpdate<'a, K, C> {
#[inline]
fn add(&mut self, _: K, _: C) -> Result<(), Error> {
Err(Error::ListChangeWrong)
}
#[inline]
fn reuse(&mut self, _: K) -> Result<&mut C, Error> {
Err(Error::ListChangeWrong)
}
#[inline]
fn finish(self, _: impl FnMut(C) -> Result<(), Error>) -> Result<(), Error> {
Ok(())
}
}
#[derive(Debug)]
pub struct StaticSingleSlot<K, C> {
kc: Option<C>,
phantom: PhantomData<K>,
}
impl<K, C> Default for StaticSingleSlot<K, C> {
#[inline]
fn default() -> Self
where
Self: Sized,
{
Self {
kc: None,
phantom: PhantomData,
}
}
}
impl<K, C> SlotKindTrait<K, C> for StaticSingleSlot<K, C> {
type Update<'a> = StaticSingleSlotUpdate<'a, K, C> where K: 'a, C: 'a;
type Iter<'a> = std::option::IntoIter<&'a C> where K: 'a, C: 'a;
#[inline(always)]
fn may_update(&self) -> bool {
false
}
#[inline(always)]
fn add(&mut self, _: K, c: C) -> Result<(), Error> {
if self.kc.is_some() {
return Err(Error::ListChangeWrong);
}
self.kc = Some(c);
Ok(())
}
#[inline(always)]
fn remove(&mut self, _: K) -> Result<C, Error> {
if self.kc.is_none() {
return Err(Error::ListChangeWrong);
}
match self.kc.take() {
Some(c) => Ok(c),
None => Err(Error::ListChangeWrong),
}
}
#[inline]
fn get(&self, _: K) -> Result<&C, Error> {
self.kc.as_ref().ok_or(Error::ListChangeWrong)
}
#[inline]
fn get_mut(&mut self, _: K) -> Result<&mut C, Error> {
self.kc.as_mut().ok_or(Error::ListChangeWrong)
}
#[inline]
fn update<'a>(&'a mut self) -> Self::Update<'a> {
StaticSingleSlotUpdate {
s: self,
visited: false,
}
}
#[inline]
fn iter<'a>(&'a self) -> Self::Iter<'a> {
self.kc.as_ref().into_iter()
}
#[inline]
fn single_slot(&self) -> Option<&C> {
self.kc.as_ref()
}
}
#[doc(hidden)]
pub struct StaticSingleSlotUpdate<'a, K, C> {
s: &'a mut StaticSingleSlot<K, C>,
visited: bool,
}
impl<'a, K, C> SlotKindUpdateTrait<'a, K, C> for StaticSingleSlotUpdate<'a, K, C> {
#[inline]
fn add(&mut self, k: K, c: C) -> Result<(), Error> {
let ret = self.s.add(k, c);
if ret.is_ok() {
self.visited = true;
}
ret
}
#[inline]
fn reuse(&mut self, k: K) -> Result<&mut C, Error> {
let ret = self.s.get_mut(k);
if ret.is_ok() {
self.visited = true;
}
ret
}
#[inline]
fn finish(self, mut remove_item_fn: impl FnMut(C) -> Result<(), Error>) -> Result<(), Error> {
if !self.visited {
if let Some(c) = self.s.kc.take() {
return remove_item_fn(c);
}
}
Ok(())
}
}
#[derive(Debug)]
pub struct DynamicSlot<K, C> {
slots: HashMap<K, C>,
}
impl<K, C> Default for DynamicSlot<K, C> {
#[inline]
fn default() -> Self
where
Self: Sized,
{
Self {
slots: HashMap::new(),
}
}
}
impl<K: Hash + Eq, C> SlotKindTrait<K, C> for DynamicSlot<K, C> {
type Update<'a> = DynamicSlotUpdate<'a, K, C> where K: 'a, C: 'a;
type Iter<'a> = std::collections::hash_map::Values<'a, K, C> where K: 'a, C: 'a;
#[inline(always)]
fn may_update(&self) -> bool {
true
}
#[inline]
fn add(&mut self, k: K, v: C) -> Result<(), Error> {
self.slots.insert(k, v);
Ok(())
}
#[inline]
fn remove(&mut self, k: K) -> Result<C, Error> {
self.slots.remove(&k).ok_or(Error::ListChangeWrong)
}
#[inline]
fn get(&self, k: K) -> Result<&C, Error> {
self.slots.get(&k).ok_or(Error::ListChangeWrong)
}
#[inline]
fn get_mut(&mut self, k: K) -> Result<&mut C, Error> {
self.slots.get_mut(&k).ok_or(Error::ListChangeWrong)
}
#[inline]
fn update(&mut self) -> Self::Update<'_> {
DynamicSlotUpdate {
cur_map: HashMap::with_capacity(self.slots.len()),
old: self,
}
}
#[inline]
fn iter(&self) -> Self::Iter<'_> {
self.slots.values()
}
#[inline]
fn single_slot(&self) -> Option<&C> {
match self.slots.len() {
1 => self.slots.values().next(),
_ => None,
}
}
}
#[doc(hidden)]
pub struct DynamicSlotUpdate<'a, K, C> {
cur_map: HashMap<K, C>,
old: &'a mut DynamicSlot<K, C>,
}
impl<'a, K: Hash + Eq, C> SlotKindUpdateTrait<'a, K, C> for DynamicSlotUpdate<'a, K, C> {
#[inline]
fn add(&mut self, k: K, v: C) -> Result<(), Error> {
self.cur_map.insert(k, v);
Ok(())
}
#[inline]
fn reuse(&mut self, k: K) -> Result<&mut C, Error> {
let c = self.old.slots.remove(&k).ok_or(Error::ListChangeWrong)?;
let ret = self.cur_map.entry(k).or_insert(c);
Ok(ret)
}
#[inline]
fn finish(self, mut item_fn: impl FnMut(C) -> Result<(), Error>) -> Result<(), Error> {
let r = std::mem::replace(&mut self.old.slots, self.cur_map);
for (_, c) in r {
item_fn(c)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum SlotChange<N, M, T> {
Unchanged(N, M, T),
DataChanged(N, M, T),
Added(N, M, T),
Removed(M),
}