use crate::conversion::{type_to_cpp, ConvertError};
use crate::{known_types::type_lacks_copy_constructor, types::Namespace};
use syn::{parse_quote, Ident, Type};
#[derive(Clone)]
enum ArgumentConversionType {
None,
FromUniquePtrToValue,
FromValueToUniquePtr,
}
#[derive(Clone)]
pub(crate) struct ArgumentConversion {
unwrapped_type: Type,
conversion: ArgumentConversionType,
}
impl ArgumentConversion {
pub(crate) fn new_unconverted(ty: Type) -> Self {
ArgumentConversion {
unwrapped_type: ty,
conversion: ArgumentConversionType::None,
}
}
pub(crate) fn new_to_unique_ptr(ty: Type) -> Self {
ArgumentConversion {
unwrapped_type: ty,
conversion: ArgumentConversionType::FromValueToUniquePtr,
}
}
pub(crate) fn new_from_unique_ptr(ty: Type) -> Self {
ArgumentConversion {
unwrapped_type: ty,
conversion: ArgumentConversionType::FromUniquePtrToValue,
}
}
pub(crate) fn work_needed(&self) -> bool {
!matches!(self.conversion, ArgumentConversionType::None)
}
pub(crate) fn unconverted_type(&self) -> Result<String, ConvertError> {
match self.conversion {
ArgumentConversionType::FromUniquePtrToValue => self.wrapped_type(),
_ => self.unwrapped_type_as_string(),
}
}
pub(crate) fn converted_type(&self) -> Result<String, ConvertError> {
match self.conversion {
ArgumentConversionType::FromValueToUniquePtr => self.wrapped_type(),
_ => self.unwrapped_type_as_string(),
}
}
pub(crate) fn unconverted_rust_type(&self) -> Type {
match self.conversion {
ArgumentConversionType::FromValueToUniquePtr => self.make_unique_ptr_type(),
_ => self.unwrapped_type.clone(),
}
}
pub(crate) fn converted_rust_type(&self) -> Type {
match self.conversion {
ArgumentConversionType::FromUniquePtrToValue => self.make_unique_ptr_type(),
_ => self.unwrapped_type.clone(),
}
}
fn unwrapped_type_as_string(&self) -> Result<String, ConvertError> {
type_to_cpp(&self.unwrapped_type)
}
fn wrapped_type(&self) -> Result<String, ConvertError> {
Ok(format!(
"std::unique_ptr<{}>",
self.unwrapped_type_as_string()?
))
}
pub(crate) fn conversion(&self, var_name: &str) -> Result<String, ConvertError> {
Ok(match self.conversion {
ArgumentConversionType::None => {
if type_lacks_copy_constructor(&self.unwrapped_type) {
format!("std::move({})", var_name)
} else {
var_name.to_string()
}
}
ArgumentConversionType::FromUniquePtrToValue => format!("std::move(*{})", var_name),
ArgumentConversionType::FromValueToUniquePtr => format!(
"std::make_unique<{}>({})",
self.unconverted_type()?,
var_name
),
})
}
fn make_unique_ptr_type(&self) -> Type {
let innerty = &self.unwrapped_type;
parse_quote! {
cxx::UniquePtr < #innerty >
}
}
}
#[derive(Clone)] pub(crate) enum FunctionWrapperPayload {
FunctionCall(Namespace, Ident),
StaticMethodCall(Namespace, Ident, Ident),
Constructor,
}
#[derive(Clone)] pub(crate) struct FunctionWrapper {
pub(crate) payload: FunctionWrapperPayload,
pub(crate) wrapper_function_name: Ident,
pub(crate) return_conversion: Option<ArgumentConversion>,
pub(crate) argument_conversion: Vec<ArgumentConversion>,
pub(crate) is_a_method: bool,
}