ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use std::fmt::{Debug, Formatter};
use quote::ToTokens;
use syn::__private::TokenStream2;
use syn::Type;
use crate::composer::SignatureAspect;
use crate::ext::{AsType, ExpressionComposable, GenericNestedArg, ToType};
use crate::lang::Specification;
use crate::presentable::{Aspect, BindingPresentableContext, Expression, ScopeContextPresentable, SmartPointerPresentableContext};
use crate::presentation::DictionaryExpr;


#[derive(Clone, PartialEq, Eq)]
pub enum SmartPointerKind {
    Box(Type),
    Rc(Type),
    Arc(Type),

    Cell(Type),
    RefCell(Type),
    UnsafeCell(Type),

    Mutex(Type),
    OnceLock(Type),
    RwLock(Type),

    Pin(Type),
}
impl SmartPointerKind {
    pub fn is_once_lock(&self) -> bool {
        matches!(self, Self::OnceLock(_))
    }
    pub fn dictionary_type(&self) -> DictionaryExpr {
        match self {
            Self::Box(_) => DictionaryExpr::Box,
            Self::Arc(_) => DictionaryExpr::Arc,
            Self::Rc(_) => DictionaryExpr::Rc,
            Self::Mutex(_) => DictionaryExpr::Mutex,
            Self::OnceLock(_) => DictionaryExpr::OnceLock,
            Self::RwLock(_) => DictionaryExpr::RwLock,
            Self::Cell(_) => DictionaryExpr::Cell,
            Self::RefCell(_) => DictionaryExpr::RefCell,
            Self::UnsafeCell(_) => DictionaryExpr::UnsafeCell,
            _ => panic!("SmartPointerKind::dictionary_type")
        }
    }

    pub fn wrapped_arg_type(&self) -> Option<&Type> {
        match self {
            Self::Rc(_) |
            Self::Arc(_) =>
                self.as_type().maybe_first_nested_type_ref()?.maybe_first_nested_type_ref(),
            _ => self.as_type().maybe_first_nested_type_ref()
        }
    }
    pub fn wrap_alloc<SPEC>(&self, expr: SPEC::Expr) -> SPEC::Expr
    where SPEC: Specification<Expr=Expression<SPEC>>,
          Expression<SPEC>: ScopeContextPresentable {
        match self {
            Self::Rc(_) |
            Self::Arc(_) => SPEC::Expr::new_smth(expr, self.dictionary_type()),
            _ => expr,
        }
    }
    pub fn wrap_from<SPEC, T>(&self, expr: T) -> SPEC::Expr
    where SPEC: Specification<Expr=Expression<SPEC>>,
          Expression<SPEC>: ScopeContextPresentable,
          T: ToTokens {
        match self {
            Self::Rc(_) => SPEC::Expr::dict_expr(DictionaryExpr::from_rc(DictionaryExpr::deref_ref(expr))),
            Self::Arc(_) => SPEC::Expr::dict_expr(DictionaryExpr::from_arc(DictionaryExpr::deref_ref(expr))),
            Self::Mutex(_) |
            Self::OnceLock(_) |
            Self::RwLock(_) |
            Self::Cell(_) |
            Self::RefCell(_) |
            Self::UnsafeCell(_) => SPEC::Expr::dict_expr(DictionaryExpr::from_ptr_read(expr)),
            _ => SPEC::Expr::simple(expr),
        }
    }
    pub fn wrap_arg_to<SPEC>(&self, expr: Expression<SPEC>) -> Expression<SPEC>
    where SPEC: Specification<Expr=Expression<SPEC>>,
          Expression<SPEC>: ScopeContextPresentable {
        match self {
            Self::Cell(_) => expr,
            _ => expr.cloned(),
        }
    }
    pub fn binding_presentable<SPEC: Specification>(
        &self,
        aspect: &Aspect<SPEC::TYC>,
        signature_aspect: &SignatureAspect<SPEC>,
        context: SmartPointerPresentableContext<SPEC>
    ) -> BindingPresentableContext<SPEC> {
        BindingPresentableContext::smart_pointer(self, aspect, signature_aspect, context)
    }
}
impl Debug for SmartPointerKind {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_fmt(format_args!("SmartPointerKind::{}({})", match self {
            Self::Box(_) => "Box",
            Self::Rc(_) => "Rc",
            Self::Arc(_) => "Arc",
            Self::Cell(_) => "Cell",
            Self::RefCell(_) => "RefCell",
            Self::UnsafeCell(_) => "UnsafeCell",
            Self::Mutex(_) => "Mutex",
            Self::RwLock(_) => "RwLock",
            Self::OnceLock(_) => "OnceLock",
            Self::Pin(_) => "Pin",
        }, self.to_token_stream()))
    }
}

impl ToTokens for SmartPointerKind {
    fn to_tokens(&self, tokens: &mut TokenStream2) {
        self.as_type().to_tokens(tokens);
    }
}

impl<'a> AsType<'a> for SmartPointerKind{
    fn as_type(&'a self) -> &'a Type {
        match self {
            Self::Box(ty) |
            Self::Rc(ty) |
            Self::Arc(ty) |
            Self::Cell(ty) |
            Self::RefCell(ty) |
            Self::UnsafeCell(ty) |
            Self::Mutex(ty) |
            Self::RwLock(ty) |
            Self::OnceLock(ty) |
            Self::Pin(ty) => ty,
        }
    }
}
impl ToType for SmartPointerKind {
    fn to_type(&self) -> Type {
        self.as_type().clone()
    }
}