use std::mem;
use std::hint::unreachable_unchecked;
use std::marker::PhantomData;
use std::ops::{ Deref, DerefMut };
use std::option::{ Iter, IterMut };
use crate::traits::node_tree::NodeTree;
use super::rid::RID;
use super::logger::Log;
use super::tree_result::TreeResult;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TreeOption<'a, T> {
tree: *mut dyn NodeTree,
owner: RID,
object: Option<T>,
p_life: PhantomData<&'a ()>
}
impl <'a, T> TreeOption<'a, T> {
#[inline]
pub const unsafe fn new(tree: *mut dyn NodeTree, owner: RID, object: Option<T>) -> Self {
TreeOption { tree, owner, object, p_life: PhantomData }
}
#[inline]
pub fn to_option(self) -> Option<T> {
self.object
}
#[inline]
pub const fn is_some(&self) -> bool {
self.object.is_some()
}
#[inline]
pub fn is_some_and(&self, f: impl FnOnce(&T) -> bool) -> bool {
self.object.as_ref().is_some_and(f)
}
#[inline]
pub const fn is_none(&self) -> bool {
self.object.is_none()
}
#[inline]
pub const fn as_ref(&self) -> TreeOption<&T> {
TreeOption { tree: self.tree, owner: self.owner, object: self.object.as_ref(), p_life: self.p_life }
}
#[inline]
pub fn as_mut(&mut self) -> TreeOption<&mut T> {
TreeOption { tree: self.tree, owner: self.owner, object: self.object.as_mut(), p_life: self.p_life }
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self.object.as_slice()
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.object.as_mut_slice()
}
#[inline]
pub fn expect(self, msg: &str) -> T {
match self.object {
Some(object) => object,
None => self.fail(msg)
}
}
#[inline(always)]
pub fn unwrap(self) -> T {
match self.object {
Some(object) => object,
None => self.fail("called `TreeOption::unwrap()` on a `None` value")
}
}
#[inline]
pub fn unwrap_or(self, default: T) -> T {
match self.object {
Some(object) => object,
None => default
}
}
#[inline]
pub fn unwrap_or_else<F>(self, f: F) -> T
where
F: FnOnce() -> T,
{
self.object.unwrap_or_else(f)
}
pub fn unwrap_or_default(self) -> T
where
T: Default,
{
self.object.unwrap_or_default()
}
#[inline]
pub unsafe fn unwrap_unchecked(self) -> T {
match self.object {
Some(object) => object,
None => unsafe { unreachable_unchecked() },
}
}
#[inline]
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> TreeOption<'a, U> {
TreeOption { tree: self.tree, owner: self.owner, object: self.object.map(f), p_life: self.p_life }
}
#[inline]
pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self {
if let Some(ref x) = self.object {
f(x);
}
self
}
#[inline]
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
self.object.map_or(default, f)
}
#[inline]
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
where
D: FnOnce() -> U,
F: FnOnce(T) -> U,
{ self.object.map_or_else(default, f) }
#[inline]
pub fn ok_or<E>(self, err: E) -> TreeResult<'a, T, E> {
unsafe {
TreeResult::new(self.tree, self.owner, self.object.ok_or(err))
}
}
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> TreeResult<'a, T, E> {
unsafe {
TreeResult::new(self.tree, self.owner, self.object.ok_or_else(err))
}
}
#[inline]
pub fn as_deref(&self) -> TreeOption<&T::Target>
where
T: Deref,
{ self.as_another(self.object.as_deref()) }
#[inline]
pub fn as_deref_mut(&mut self) -> TreeOption<&mut T::Target>
where
T: DerefMut,
{ TreeOption { tree: self.tree, owner: self.owner, object: self.object.as_deref_mut(), p_life: self.p_life } }
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
self.object.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
self.object.iter_mut()
}
#[inline]
pub fn and<'b, U>(self, optb: TreeOption<'b, U>) -> TreeOption<'a, U> {
match self.object {
Some(_) => self.transfer_owner(optb),
None => self.as_none()
}
}
#[inline]
#[doc(alias = "flatmap")]
pub fn and_then<'b, U, F: FnOnce(T) -> TreeOption<'b, U>>(self, f: F) -> TreeOption<'a, U> {
match self.object {
Some(x) => TreeOption { tree: self.tree, owner: self.owner, object: f(x).to_option(), p_life: self.p_life },
None => TreeOption { tree: self.tree, owner: self.owner, object: None, p_life: self.p_life }
}
}
#[inline]
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
if let Some(ref x) = self.object {
if predicate(x) {
return self;
}
}
self.as_none()
}
pub fn or<'b>(self, optb: TreeOption<'b, T>) -> TreeOption<'a, T> {
match self.object {
object @ Some(_) => TreeOption { tree: self.tree, owner: self.owner, object, p_life: self.p_life },
None => self.transfer_owner(optb)
}
}
#[inline]
pub fn or_else<'b, F: FnOnce() -> TreeOption<'b, T>>(self, f: F) -> TreeOption<'a, T> {
match self.object {
object @ Some(_) => TreeOption { tree: self.tree, owner: self.owner, object, p_life: self.p_life },
None => self.transfer_owner(f()),
}
}
#[inline]
pub fn xor<'b>(self, optb: TreeOption<'b, T>) -> TreeOption<'a, T> {
match (self.object, optb.object) {
(opta @ Some(_), None) => TreeOption { tree: self.tree, owner: self.owner, object: opta, p_life: self.p_life },
(None, optb @ Some(_)) => TreeOption { tree: self.tree, owner: self.owner, object: optb, p_life: self.p_life },
_ => TreeOption { tree: self.tree, owner: self.owner, object: None, p_life: self.p_life }
}
}
#[inline]
pub fn insert(&mut self, value: T) -> &mut T {
self.object = Some(value);
unsafe { self.as_mut().unwrap_unchecked() }
}
#[inline]
pub fn get_or_insert(&mut self, value: T) -> &mut T {
if self.object.is_none() {
self.object = Some(value);
}
unsafe { self.as_mut().unwrap_unchecked() }
}
#[inline]
pub fn get_or_insert_default(&mut self) -> &mut T
where
T: Default,
{ self.get_or_insert_with(T::default) }
#[inline]
pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
if self.object.is_none() {
self.object = Some(f());
}
unsafe { self.as_mut().unwrap_unchecked() }
}
#[inline]
pub fn take(&mut self) -> TreeOption<T> {
TreeOption {
owner: self.owner,
tree: self.tree,
object: self.object.take(),
p_life: self.p_life
}
}
#[inline]
pub fn take_if<P: FnOnce(&mut T) -> bool>(&mut self, predicate: P) -> TreeOption<T> {
TreeOption {
tree: self.tree,
owner: self.owner,
object: if self.as_mut().map_or(false, predicate) { self.object.take() } else { None },
p_life: self.p_life
}
}
#[inline]
pub fn replace(&mut self, value: T) -> Option<T> {
mem::replace(&mut self.object, Some(value))
}
pub fn zip<'b, U>(self, other: TreeOption<'b, U>) -> TreeOption<'a, (T, U)> {
TreeOption {
tree: self.tree,
owner: self.owner,
object: self.object.zip(other.object),
p_life: self.p_life
}
}
pub fn transfer_owner<'b, U>(&self, other: TreeOption<'b, U>) -> TreeOption<'a, U> {
TreeOption { tree: self.tree, owner: self.owner, object: other.object, p_life: self.p_life}
}
fn fail(&self, msg: &str) -> ! {
unsafe { (*self.tree).get_node(self.owner).unwrap_unchecked() }.post(Log::Panic(msg));
println!("\n[RUST TRACE]");
panic!();
}
fn as_another<U>(&self, object: Option<U>) -> TreeOption<'a, U> {
TreeOption { tree: self.tree, owner: self.owner, object, p_life: self.p_life }
}
fn as_none<U>(&self) -> TreeOption<'a, U> {
TreeOption { tree: self.tree, owner: self.owner, object: None, p_life: self.p_life }
}
}
impl <'a, T, U> TreeOption<'a, (T, U)> {
#[inline]
pub fn unzip(self) -> (TreeOption<'a, T>, TreeOption<'a, U>) {
match self.object {
Some((a, b)) => (TreeOption {
tree: self.tree,
owner: self.owner,
object: Some(a),
p_life: self.p_life
}, TreeOption {
tree: self.tree,
owner: self.owner,
object: Some(b),
p_life: self.p_life
}),
None => (self.as_none(), self.as_none()),
}
}
}
impl <'a, T> TreeOption<'a, &T> {
pub fn copied(self) -> TreeOption<'a, T>
where
T: Copy,
{ self.map(|x| *x) }
pub fn cloned(self) -> TreeOption<'a, T>
where
T: Clone,
{ self.map(|x| x.to_owned()) }
}
impl <'a, T> TreeOption<'a, &mut T> {
pub fn copied(self) -> TreeOption<'a, T>
where
T: Copy,
{ self.map(|x| *x) }
pub fn cloned(self) -> TreeOption<'a, T>
where
T: Clone,
{ self.map(|x| x.to_owned()) }
}
impl <'a, 'b, T, E> TreeOption<'a, TreeResult<'b, T, E>> {
#[inline]
pub fn transpose(self) -> TreeResult<'a, TreeOption<'a, T>, E> {
match self.object {
Some(inner) => {
match inner.to_result() {
Ok(x) => unsafe { TreeResult::new(self.tree, self.owner, Ok(TreeOption::new(self.tree, self.owner, Some(x)))) },
Err(e) => unsafe { TreeResult::new(self.tree, self.owner, Err(e)) },
}
},
None => unsafe { TreeResult::new(self.tree, self.owner, Ok(TreeOption::new(self.tree, self.owner, None))) }
}
}
}
impl <'a, 'b, T> TreeOption<'a, TreeOption<'b, T>> {
pub fn flatten(self) -> TreeOption<'a, T> {
match self.object {
Some(object) => TreeOption { tree: self.tree, owner: self.owner, object: object.to_option(), p_life: self.p_life },
None => self.as_none()
}
}
}