use std::any::TypeId;
pub trait BiplateYes {
type Src;
type Dest: Eq + Clone;
fn spez_try_biplate(&self) -> (Tree<Self::Dest>, Box<dyn Fn(Tree<Self::Dest>) -> Self::Src>);
#[allow(missing_docs)]
fn spez_impls_biplate(&self) -> bool;
}
pub trait BiplateNo {
type Src;
type Dest: Eq + Clone;
fn spez_try_biplate(&self) -> (Tree<Self::Dest>, Box<dyn Fn(Tree<Self::Dest>) -> Self::Src>);
#[allow(missing_docs)]
fn spez_impls_biplate(&self) -> bool;
}
impl<Src, Dest> BiplateYes for &SpezBiplate<Src, Dest>
where
Src: Biplate<Dest>,
Dest: Eq + Clone + Uniplate,
{
type Src = Src;
type Dest = Dest;
fn spez_try_biplate(&self) -> (Tree<Self::Dest>, Box<dyn Fn(Tree<Self::Dest>) -> Self::Src>) {
self.0.biplate()
}
#[inline(always)]
fn spez_impls_biplate(&self) -> bool {
true
}
}
impl<Src, Dest> BiplateNo for SpezBiplate<Src, Dest>
where
Src: Eq + Clone + 'static,
Dest: Eq + Clone + 'static,
{
type Src = Src;
type Dest = Dest;
fn spez_try_biplate(&self) -> (Tree<Self::Dest>, Box<dyn Fn(Tree<Self::Dest>) -> Self::Src>) {
if TypeId::of::<Src>() == TypeId::of::<Dest>() {
unsafe {
let this_as_dest: Dest = (std::mem::transmute::<&Src, &Dest>(&self.0)).clone();
let tree = Tree::One(this_as_dest);
let ctx = Box::new(move |x| {
let Tree::One(x) = x else {
panic!();
};
std::mem::transmute::<&Dest, &Src>(&x).clone()
});
(tree, ctx)
}
} else {
let this = self.0.clone();
(Tree::Zero, Box::new(move |_| this.clone()))
}
}
#[inline(always)]
fn spez_impls_biplate(&self) -> bool {
false
}
}
#[doc(inline)]
pub use crate::try_biplate_to;
#[macro_export]
#[doc(hidden)]
macro_rules! try_biplate_to {
($x:expr,$t:ty) => {{
#[allow(unused_imports)]
use ::uniplate::spez::{BiplateNo, BiplateYes, SpezBiplate};
#[allow(clippy::needless_borrow)]
(&&SpezBiplate($x, std::marker::PhantomData::<$t>)).spez_try_biplate()
}};
}
use crate::Biplate;
use crate::Tree;
use crate::Uniplate;
#[doc(inline)]
pub use crate::impls_biplate_to;
use super::SpezBiplate;
#[macro_export]
#[doc(hidden)]
macro_rules! impls_biplate_to {
($x:expr,$t:ty) => {{
#[allow(unused_imports)]
use ::uniplate::spez::{BiplateNo as _, BiplateYes as _, SpezBiplate};
#[allow(clippy::needless_borrow)]
(&&SpezBiplate($x, std::marker::PhantomData::<$t>)).spez_impls_biplate()
}};
}