#[allow(clippy::wildcard_imports)]
use crate::*;
use std::any::Any;
use std::cell::{Ref, RefCell};
use std::marker::PhantomData;
use std::rc::Rc;
pub trait DynamicTokens: Any + ToTokens + std::fmt::Debug {
fn as_any(&self) -> &dyn Any;
}
impl<T: Any + ToTokens + std::fmt::Debug> DynamicTokens for T {
fn as_any(&self) -> &dyn Any {
self
}
}
#[derive(Clone, Debug)]
pub struct DynNode<T = Nothing>(pub Rc<RefCell<Box<dyn DynamicTokens>>>, PhantomData<T>);
impl<T> DynNode<T> {
pub fn replace_all_with<U: DynamicTokens>(&self, this: U) -> Box<dyn DynamicTokens> {
std::mem::replace(&mut self.0.borrow_mut(), Box::new(this))
}
#[allow(clippy::return_self_not_must_use)]
pub fn replace_here_with<U: DynamicTokens>(&mut self, this: U) -> Self {
Self(
std::mem::replace(&mut self.0, Rc::new(RefCell::new(Box::new(this)))),
PhantomData,
)
}
#[must_use]
pub fn downcast_ref<U: DynamicTokens>(&self) -> Option<Ref<'_, U>> {
Ref::filter_map(self.0.borrow(), |boxed| {
boxed.as_any().downcast_ref::<U>()
})
.ok()
}
}
impl<T> Parser for DynNode<T>
where
T: Parse + DynamicTokens,
{
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let t = tokens.parse::<T>().refine_err::<Self>()?;
Ok(Self(Rc::new(RefCell::new(Box::new(t))), PhantomData))
}
}
impl<T> ToTokens for DynNode<T> {
#[inline]
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.borrow().to_tokens(tokens);
}
}