use crate::{
conversion::api::SubclassName,
types::{Namespace, QualifiedName},
};
use syn::{parse_quote, Ident, Type};
#[derive(Clone, Debug)]
pub(crate) enum CppConversionType {
None,
Move,
FromUniquePtrToValue,
FromPtrToValue,
FromValueToUniquePtr,
FromPtrToMove,
}
impl CppConversionType {
fn inverse(&self) -> Self {
match self {
CppConversionType::None => CppConversionType::None,
CppConversionType::FromUniquePtrToValue | CppConversionType::FromPtrToValue => {
CppConversionType::FromValueToUniquePtr
}
CppConversionType::FromValueToUniquePtr => CppConversionType::FromUniquePtrToValue,
_ => panic!("Did not expect to have to invert this conversion"),
}
}
}
#[derive(Clone, Debug)]
pub(crate) enum RustConversionType {
None,
FromStr,
ToBoxedUpHolder(SubclassName),
FromPinMaybeUninitToPtr,
FromPinMoveRefToPtr,
FromTypeToPtr,
FromValueParamToPtr,
}
impl RustConversionType {
pub(crate) fn requires_mutability(&self) -> Option<syn::token::Mut> {
match self {
Self::FromPinMoveRefToPtr => Some(parse_quote! { mut }),
_ => None,
}
}
}
#[derive(Clone)]
pub(crate) struct TypeConversionPolicy {
pub(crate) unwrapped_type: Type,
pub(crate) cpp_conversion: CppConversionType,
pub(crate) rust_conversion: RustConversionType,
}
impl TypeConversionPolicy {
pub(crate) fn new_unconverted(ty: Type) -> Self {
TypeConversionPolicy {
unwrapped_type: ty,
cpp_conversion: CppConversionType::None,
rust_conversion: RustConversionType::None,
}
}
pub(crate) fn new_to_unique_ptr(ty: Type) -> Self {
TypeConversionPolicy {
unwrapped_type: ty,
cpp_conversion: CppConversionType::FromValueToUniquePtr,
rust_conversion: RustConversionType::None,
}
}
pub(crate) fn cpp_work_needed(&self) -> bool {
!matches!(self.cpp_conversion, CppConversionType::None)
}
pub(crate) fn unconverted_rust_type(&self) -> Type {
match self.cpp_conversion {
CppConversionType::FromValueToUniquePtr => self.make_unique_ptr_type(),
_ => self.unwrapped_type.clone(),
}
}
pub(crate) fn converted_rust_type(&self) -> Type {
match self.cpp_conversion {
CppConversionType::FromUniquePtrToValue => self.make_unique_ptr_type(),
CppConversionType::FromPtrToValue => {
let innerty = &self.unwrapped_type;
parse_quote! {
*mut #innerty
}
}
_ => self.unwrapped_type.clone(),
}
}
fn make_unique_ptr_type(&self) -> Type {
let innerty = &self.unwrapped_type;
parse_quote! {
cxx::UniquePtr < #innerty >
}
}
pub(crate) fn rust_work_needed(&self) -> bool {
!matches!(self.rust_conversion, RustConversionType::None)
}
pub(crate) fn inverse(&self) -> Self {
Self {
unwrapped_type: self.unwrapped_type.clone(),
cpp_conversion: self.cpp_conversion.inverse(),
rust_conversion: self.rust_conversion.clone(),
}
}
pub(crate) fn bridge_unsafe_needed(&self) -> bool {
matches!(
self.rust_conversion,
RustConversionType::FromValueParamToPtr
)
}
}
#[derive(Clone)]
pub(crate) enum CppFunctionBody {
FunctionCall(Namespace, Ident),
StaticMethodCall(Namespace, Ident, Ident),
PlacementNew(Namespace, Ident),
MakeUnique,
ConstructSuperclass(String),
Cast,
Destructor(Namespace, Ident),
AllocUninitialized(QualifiedName),
FreeUninitialized(QualifiedName),
}
#[derive(Clone)]
pub(crate) enum CppFunctionKind {
Function,
Method,
Constructor,
ConstMethod,
SynthesizedConstructor,
}
#[derive(Clone)]
pub(crate) struct CppFunction {
pub(crate) payload: CppFunctionBody,
pub(crate) wrapper_function_name: Ident,
pub(crate) original_cpp_name: String,
pub(crate) return_conversion: Option<TypeConversionPolicy>,
pub(crate) argument_conversion: Vec<TypeConversionPolicy>,
pub(crate) kind: CppFunctionKind,
pub(crate) pass_obs_field: bool,
pub(crate) qualification: Option<QualifiedName>,
}