use std::ops::{ Deref, DerefMut };
use std::any::Any;
use std::marker::PhantomData;
use thiserror::Error;
use portable_intertrait::cast::*;
use crate::traits::{ node::Node, node_tree::NodeTree };
use super::rid::RID;
use super::logger::Log;
use super::tree_result::TreeResult;
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TPError {
#[error("The node exists but ultimately is of the wrong type")]
WrongType,
#[error("A non-existent node was referenced")]
IsNull,
#[error("Cannot cast a null Tp<T> to a dynamic TpDyn")]
AttemptedCastToDynOnNull,
#[error("Cannot coerce a null TpDyn to a dynamic trait object")]
AttemptedDynCastOnNull,
#[error("The held node by this TpDyn does not extend the specified trait")]
DynCastFailed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Tp<'a, T: Node> {
tree: *mut dyn NodeTree,
owner: RID,
node: RID,
p_life: PhantomData<&'a ()>,
p_type: PhantomData<T>
}
impl <'a, T: Node> Tp<'a, T> {
pub unsafe fn new(tree: *mut dyn NodeTree, owner: RID, node: RID) -> TreeResult<'a, Self, TPError> {
match unsafe { &*tree }.get_node(node) {
Some(node) => {
let any: &dyn Any = node.as_any_ref();
match any.downcast_ref::<T>() {
Some(_) => (),
None => return unsafe { TreeResult::new(tree, owner, Err(TPError::WrongType)) }
}
},
None => return unsafe { TreeResult::new(tree, owner, Err(TPError::IsNull)) }
}
unsafe {
TreeResult::new(tree, owner, Ok(Tp {
tree,
owner,
node,
p_life: PhantomData,
p_type: PhantomData
}))
}
}
#[inline]
pub fn to_dyn(self) -> TpDyn<'a> {
unsafe {
match TpDyn::new(self.tree, self.owner, self.node).ok().to_option() {
Some(success) => success,
None => self.fail(TPError::AttemptedCastToDynOnNull)
}
}
}
#[inline]
pub fn try_to_dyn(self) -> TreeResult<'a, TpDyn<'a>, TPError> {
unsafe {
TpDyn::new(self.tree, self.owner, self.node)
}
}
#[inline]
pub fn is_valid(&self) -> bool {
match unsafe { &*self.tree }.get_node(self.node) {
Some(node) => {
let any: &dyn Any = node.as_any_ref();
any.downcast_ref::<T>().is_some()
},
None => false
}
}
#[inline]
pub fn is_null(&self) -> bool {
match unsafe { &*self.tree }.get_node(self.node) {
Some(node) => {
let any: &dyn Any = node.as_any_ref();
any.downcast_ref::<T>().is_none()
},
None => true
}
}
pub fn get(&self) -> &T {
let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
match node {
Some(node) => {
let any: &dyn Any = node.as_any_ref();
match any.downcast_ref::<T>() {
Some(node) => node,
None => self.fail(TPError::WrongType)
}
},
None => self.fail(TPError::IsNull)
}
}
pub fn try_get(&self) -> TreeResult<&T, TPError> {
let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
match node {
Some(node) => {
let any: &dyn Any = node.as_any_ref();
match any.downcast_ref::<T>() {
Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::WrongType)) }
}
},
None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
}
}
pub fn get_mut(&mut self) -> &mut T {
let node: Option<&mut dyn Node> = unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n });
match node {
Some(node) => {
let any: &mut dyn Any = node.as_any_mut();
match any.downcast_mut::<T>() {
Some(node) => node,
None => self.fail(TPError::WrongType)
}
},
None => self.fail(TPError::IsNull)
}
}
pub fn try_get_mut(&mut self) -> TreeResult<&mut T, TPError> {
let node: Option<&mut dyn Node> = unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n });
match node {
Some(node) => {
let any: &mut dyn Any = node.as_any_mut();
match any.downcast_mut::<T>() {
Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::WrongType)) }
}
},
None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
}
}
#[inline]
fn fail(&self, err: TPError) -> ! {
unsafe { (*self.tree).get_node(self.owner).unwrap_unchecked() }.post(Log::Panic(&format!("{err:?}")));
println!("\n[RUST TRACE]");
panic!();
}
}
impl <'a, T: Node> Deref for Tp<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl <'a, T: Node> DerefMut for Tp<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.get_mut()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TpDyn<'a> {
owner: RID,
node: RID,
tree: *mut dyn NodeTree,
p_life: PhantomData<&'a ()>
}
impl <'a> TpDyn<'a> {
pub unsafe fn new(tree: *mut dyn NodeTree, owner: RID, node: RID) -> TreeResult<'a, Self, TPError> {
match unsafe { &*tree }.get_node(node) {
Some(_) => (),
None => return unsafe { TreeResult::new(tree, owner, Err(TPError::IsNull)) }
}
unsafe {
TreeResult::new(tree, owner, Ok(TpDyn {
owner,
node,
tree,
p_life: PhantomData
}))
}
}
pub fn cast<T: ?Sized + 'static>(&self) -> TreeResult<&'a T, TPError> {
use std::mem;
match self.try_get().to_option() {
Some(inner) => {
match <dyn Node as CastRef>::cast::<T>(inner) {
Some(casted) => unsafe { TreeResult::new(self.tree, self.owner, Ok(mem::transmute(casted))) }, None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::DynCastFailed)) }
}
},
None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::AttemptedDynCastOnNull)) }
}
}
#[inline]
pub fn cast_mut<T: ?Sized + 'static>(&mut self) -> TreeResult<&'a mut T, TPError> {
use std::mem;
let tree: *mut dyn NodeTree = self.tree;
let owner: RID = self.owner;
match self.try_get_mut().to_option() {
Some(inner) => {
match <dyn Node as CastMut>::cast::<T>(inner) {
Some(casted) => unsafe { TreeResult::new(tree, owner, Ok(mem::transmute(casted))) }, None => unsafe { TreeResult::new(tree, owner, Err(TPError::DynCastFailed)) }
}
},
None => unsafe { TreeResult::new(tree, owner, Err(TPError::AttemptedDynCastOnNull)) }
}
}
#[inline]
pub fn to<T: Node>(self) -> TreeResult<'a, Tp<'a, T>, TPError> {
unsafe {
Tp::new(self.tree, self.owner, self.node)
}
}
#[inline]
pub fn is_of<T: ?Sized + 'static>(&self) -> bool {
use std::mem;
let node: TpDyn = unsafe { mem::transmute(*self) };
<TpDyn as CastRef>::impls::<T>(&node)
}
pub fn is<T: Node>(&self) -> bool {
let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
match node {
Some(node) => {
let any: &dyn Any = node.as_any_ref();
any.downcast_ref::<T>().is_some()
},
None => false
}
}
#[inline]
pub fn is_valid(&self) -> bool {
unsafe { &*self.tree }.get_node(self.node).is_some()
}
#[inline]
pub fn is_null(&self) -> bool {
unsafe { &*self.tree }.get_node(self.node).is_none()
}
#[inline]
pub fn get(&self) -> &dyn Node {
let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
match node {
Some(node) => node,
None => self.fail(TPError::IsNull)
}
}
#[inline]
pub fn try_get(&self) -> TreeResult<'a, &dyn Node, TPError> {
match unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n }) {
Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
}
}
#[inline]
pub fn get_mut(&mut self) -> &mut dyn Node {
let node: Option<&mut dyn Node> = unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n });
match node {
Some(node) => node,
None => self.fail(TPError::IsNull)
}
}
#[inline]
pub fn try_get_mut(&mut self) -> TreeResult<'a, &mut dyn Node, TPError> {
match unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n }) {
Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
}
}
#[inline]
fn fail(&self, err: TPError) -> ! {
unsafe { (*self.tree).get_node(self.owner).unwrap_unchecked() }.post(Log::Panic(&format!("{err}")));
println!("\n[RUST TRACE]");
panic!();
}
}
impl <'a> Deref for TpDyn<'a> {
type Target = dyn Node;
fn deref(&self) -> &Self::Target {
self.get()
}
}
impl <'a> DerefMut for TpDyn<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.get_mut()
}
}