use abi_stable::{
std_types::{RBox, ROption, RString, RVec},
StableAbi,
};
pub use rplugin_macros::ast_for_plugin;
pub trait StableAst: StableAbi {
type Unstable: Sized;
fn from_unstable(n: Self::Unstable) -> Self;
fn into_unstable(self) -> Self::Unstable;
}
impl<T> StableAst for RBox<T>
where
T: StableAst,
{
type Unstable = Box<T::Unstable>;
fn from_unstable(n: Self::Unstable) -> Self {
RBox::new(T::from_unstable(*n))
}
fn into_unstable(self) -> Self::Unstable {
Box::new(T::into_unstable(RBox::into_inner(self)))
}
}
impl<T> StableAst for ROption<T>
where
T: StableAst,
{
type Unstable = Option<T::Unstable>;
fn from_unstable(n: Self::Unstable) -> Self {
match n {
Some(v) => ROption::RSome(T::from_unstable(v)),
None => ROption::RNone,
}
}
fn into_unstable(self) -> Self::Unstable {
match self {
ROption::RSome(v) => Some(v.into_unstable()),
ROption::RNone => None,
}
}
}
impl<T> StableAst for RVec<T>
where
T: StableAst,
{
type Unstable = Vec<T::Unstable>;
fn from_unstable(n: Self::Unstable) -> Self {
n.into_iter().map(T::from_unstable).collect()
}
fn into_unstable(self) -> Self::Unstable {
self.into_iter().map(T::into_unstable).collect()
}
}
macro_rules! as_is {
($T:ty) => {
impl StableAst for $T {
type Unstable = $T;
#[inline(always)]
fn from_unstable(n: Self::Unstable) -> Self {
n
}
#[inline(always)]
fn into_unstable(self) -> Self::Unstable {
self
}
}
};
(
$T:ty,
$($tt:tt),*
) => {
as_is!($T);
as_is!($($tt),*);
};
}
as_is!(bool);
as_is!(usize, u8, u16, u32, u64);
as_is!(isize, i8, i16, i32, i64);
as_is!(f32, f64);
macro_rules! convert {
(
$U:ty as $T:ty
) => {
impl StableAst for $T {
type Unstable = $U;
#[inline(always)]
fn from_unstable(n: Self::Unstable) -> Self {
n.into()
}
#[inline(always)]
fn into_unstable(self) -> Self::Unstable {
self.into()
}
}
};
}
convert!(String as RString);
as_is!(swc_common::Span);