use crate::types::QualifiedName;
use itertools::Itertools;
use std::collections::HashSet;
use syn::{
ForeignItemFn, Ident, ImplItem, ItemConst, ItemEnum, ItemStruct, ItemType, ItemUse, Type,
};
use super::{convert_error::ErrorContext, ConvertError};
#[derive(Copy, Clone, Eq, PartialEq)]
pub(crate) enum TypeKind {
Pod, NonPod, Abstract, }
impl TypeKind {
pub(crate) fn can_be_instantiated(&self) -> bool {
match self {
TypeKind::Pod | TypeKind::NonPod => true,
TypeKind::Abstract => false,
}
}
}
pub(crate) struct ImplBlockDetails {
pub(crate) item: ImplItem,
pub(crate) ty: Ident,
}
#[derive(Clone)]
pub(crate) struct FuncToConvert {
pub(crate) item: ForeignItemFn,
pub(crate) virtual_this_type: Option<QualifiedName>,
pub(crate) self_ty: Option<QualifiedName>,
}
pub(crate) trait AnalysisPhase {
type TypedefAnalysis;
type StructAnalysis;
type FunAnalysis;
}
pub(crate) struct NullAnalysis;
impl AnalysisPhase for NullAnalysis {
type TypedefAnalysis = ();
type StructAnalysis = ();
type FunAnalysis = ();
}
#[derive(Clone)]
pub(crate) enum TypedefKind {
Use(ItemUse),
Type(ItemType),
}
#[derive(strum_macros::Display)]
pub(crate) enum ApiDetail<T: AnalysisPhase> {
ForwardDeclaration,
ConcreteType {
rs_definition: Box<Type>,
cpp_definition: String,
},
StringConstructor,
Function {
fun: Box<FuncToConvert>,
analysis: T::FunAnalysis,
},
Const { const_item: ItemConst },
Typedef {
item: TypedefKind,
analysis: T::TypedefAnalysis,
},
Enum { item: ItemEnum },
Struct {
item: ItemStruct,
analysis: T::StructAnalysis,
},
CType { typename: QualifiedName },
IgnoredItem {
err: ConvertError,
ctx: ErrorContext,
},
}
pub(crate) struct Api<T: AnalysisPhase> {
pub(crate) name: QualifiedName,
pub(crate) cpp_name: Option<String>,
pub(crate) deps: HashSet<QualifiedName>,
pub(crate) detail: ApiDetail<T>,
}
impl<T: AnalysisPhase> std::fmt::Debug for Api<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} (kind={}, deps={})",
self.name.to_cpp_name(),
self.detail,
self.deps.iter().map(|d| d.to_cpp_name()).join(", ")
)
}
}
pub(crate) type UnanalyzedApi = Api<NullAnalysis>;
impl<T: AnalysisPhase> Api<T> {
pub(crate) fn name(&self) -> QualifiedName {
self.name.clone()
}
pub(crate) fn cxx_name(&self) -> &str {
self.cpp_name
.as_deref()
.unwrap_or_else(|| self.name.get_final_item())
}
}