use syn::{Type, TypePtr};
use crate::conversion::{
analysis::fun::function_wrapper::{CppConversionType, TypeConversionPolicy},
api::Pointerness,
ConvertErrorFromCpp,
};
use super::type_to_cpp::{type_to_cpp, CppNameMap};
impl TypeConversionPolicy {
pub(super) fn unconverted_type(
&self,
cpp_name_map: &CppNameMap,
) -> Result<String, ConvertErrorFromCpp> {
match self.cpp_conversion {
CppConversionType::FromUniquePtrToValue => self.unique_ptr_wrapped_type(cpp_name_map),
CppConversionType::FromPtrToValue => {
Ok(format!("{}*", self.unwrapped_type_as_string(cpp_name_map)?))
}
_ => self.unwrapped_type_as_string(cpp_name_map),
}
}
pub(super) fn converted_type(
&self,
cpp_name_map: &CppNameMap,
) -> Result<String, ConvertErrorFromCpp> {
match self.cpp_conversion {
CppConversionType::FromValueToUniquePtr => self.unique_ptr_wrapped_type(cpp_name_map),
CppConversionType::FromReferenceToPointer => {
let (const_string, ty) = match self.cxxbridge_type() {
Type::Ptr(TypePtr {
mutability: Some(_),
elem,
..
}) => ("", elem.as_ref()),
Type::Ptr(TypePtr { elem, .. }) => ("const ", elem.as_ref()),
_ => panic!("Not a pointer"),
};
Ok(format!(
"{}{}*",
const_string,
type_to_cpp(ty, cpp_name_map)?
))
}
_ => self.unwrapped_type_as_string(cpp_name_map),
}
}
fn unwrapped_type_as_string(
&self,
cpp_name_map: &CppNameMap,
) -> Result<String, ConvertErrorFromCpp> {
type_to_cpp(self.cxxbridge_type(), cpp_name_map)
}
pub(crate) fn is_a_pointer(&self) -> Pointerness {
match self.cxxbridge_type() {
Type::Ptr(TypePtr {
mutability: Some(_),
..
}) => Pointerness::MutPtr,
Type::Ptr(_) => Pointerness::ConstPtr,
_ => Pointerness::Not,
}
}
fn unique_ptr_wrapped_type(
&self,
original_name_map: &CppNameMap,
) -> Result<String, ConvertErrorFromCpp> {
Ok(format!(
"std::unique_ptr<{}>",
self.unwrapped_type_as_string(original_name_map)?
))
}
pub(super) fn cpp_conversion(
&self,
var_name: &str,
cpp_name_map: &CppNameMap,
is_return: bool,
) -> Result<Option<String>, ConvertErrorFromCpp> {
Ok(match self.cpp_conversion {
CppConversionType::None | CppConversionType::FromReturnValueToPlacementPtr => {
Some(var_name.to_string())
}
CppConversionType::FromPointerToReference { .. } => Some(format!("(*{var_name})")),
CppConversionType::Move => Some(format!("std::move({var_name})")),
CppConversionType::FromUniquePtrToValue | CppConversionType::FromPtrToMove => {
Some(format!("std::move(*{var_name})"))
}
CppConversionType::FromValueToUniquePtr => Some(format!(
"std::make_unique<{}>({})",
self.unconverted_type(cpp_name_map)?,
var_name
)),
CppConversionType::FromPtrToValue => {
let dereference = format!("*{var_name}");
Some(if is_return {
dereference
} else {
format!("std::move({dereference})")
})
}
CppConversionType::IgnoredPlacementPtrParameter => None,
CppConversionType::FromReferenceToPointer { .. } => Some(format!("&{var_name}")),
})
}
}