use std::{
borrow::Cow,
fmt,
};
use clang::{
Entity,
Type,
};
use crate::{
DefaultElement,
DefinitionLocation,
DependentType,
DependentTypeMode,
Element,
EntityElement,
GeneratorEnv,
ReturnTypeWrapper,
type_ref::TemplateArg,
TypeRef,
};
#[derive(Clone)]
pub struct Vector<'tu> {
type_ref: Type<'tu>,
gen_env: &'tu GeneratorEnv<'tu>,
}
impl<'tu> Vector<'tu> {
pub fn new(type_ref: Type<'tu>, gen_env: &'tu GeneratorEnv<'tu>) -> Self {
Self { type_ref, gen_env }
}
pub fn is_data_type(&self, type_ref: &TypeRef) -> bool {
type_ref.is_data_type() || type_ref.as_vector().map_or(false, |v| v.element_type().is_data_type())
}
pub fn type_ref(&self) -> TypeRef<'tu> {
TypeRef::new(self.type_ref, self.gen_env)
}
pub fn element_type(&self) -> TypeRef<'tu> {
self.type_ref().template_specialization_args().into_iter()
.find_map(|a| if let TemplateArg::Typename(type_ref) = a {
Some(type_ref)
} else {
None
}).expect("vector template argument list is empty")
}
pub fn dependent_types<D: DependentType<'tu>>(&self) -> Vec<D> {
let element_type = self.element_type();
let is_data_type = self.is_data_type(&element_type);
let mut out = element_type.dependent_types_with_mode(DependentTypeMode::ForReturn(DefinitionLocation::Type));
out.reserve(1 + if is_data_type { 3 } else { 0 });
if element_type.as_string().is_some() {
out.push(D::from_return_type_wrapper(ReturnTypeWrapper::new(
TypeRef::new(self.gen_env.resolve_type(&element_type.cpp_extern_return()).expect("Can't resolve string cpp_extern_return()"), self.gen_env),
DefinitionLocation::Custom(element_type.rust_module().into_owned()),
self.gen_env,
)));
} else {
out.push(D::from_return_type_wrapper(ReturnTypeWrapper::new(element_type.canonical_clang(), DefinitionLocation::Module, self.gen_env)));
}
if is_data_type {
out.push(D::from_return_type_wrapper(ReturnTypeWrapper::new(
TypeRef::new(self.gen_env.resolve_type("cv::_InputArray").expect("Can't resolve _InputArray"), self.gen_env),
DefinitionLocation::Custom(element_type.rust_module().into_owned()),
self.gen_env,
)));
out.push(D::from_return_type_wrapper(ReturnTypeWrapper::new(
TypeRef::new(self.gen_env.resolve_type("cv::_OutputArray").expect("Can't resolve _OutputArray"), self.gen_env),
DefinitionLocation::Custom(element_type.rust_module().into_owned()),
self.gen_env,
)));
out.push(D::from_return_type_wrapper(ReturnTypeWrapper::new(
TypeRef::new(self.gen_env.resolve_type("cv::_InputOutputArray").expect("Can't resolve _InputOutputArray"), self.gen_env),
DefinitionLocation::Custom(element_type.rust_module().into_owned()),
self.gen_env,
)));
}
out
}
pub fn rust_localalias(&self) -> Cow<str> {
format!("VectorOf{typ}", typ=self.element_type().rust_safe_id()).into()
}
pub fn rust_fullalias(&self) -> Cow<str> {
format!("types::{}", self.rust_localalias()).into()
}
}
impl<'tu> EntityElement<'tu> for Vector<'tu> {
fn entity(&self) -> Entity<'tu> {
self.type_ref.get_declaration().expect("Can't get declaration")
}
}
impl Element for Vector<'_> {
fn is_ignored(&self) -> bool {
DefaultElement::is_ignored(self) || self.element_type().is_ignored()
}
fn is_system(&self) -> bool {
DefaultElement::is_system(self)
}
fn is_public(&self) -> bool {
DefaultElement::is_public(self)
}
fn usr(&self) -> Cow<str> {
DefaultElement::usr(self)
}
fn rendered_doc_comment_with_prefix(&self, prefix: &str, opencv_version: &str) -> String {
DefaultElement::rendered_doc_comment_with_prefix(self, prefix, opencv_version)
}
fn cpp_namespace(&self) -> Cow<str> {
"std".into()
}
fn cpp_localname(&self) -> Cow<str> {
"vector".into()
}
fn rust_module(&self) -> Cow<str> {
self.element_type().rust_module().into_owned().into()
}
fn rust_namespace(&self) -> Cow<str> {
"core".into()
}
fn rust_leafname(&self) -> Cow<str> {
let mut inner_typ = self.element_type();
if let Some(inner) = inner_typ.as_pointer() { inner_typ = inner;
}
format!("Vector::<{typ}>", typ=inner_typ.rust_full()).into()
}
fn rust_localname(&self) -> Cow<str> {
DefaultElement::rust_localname(self)
}
}
impl fmt::Display for Vector<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.entity().get_display_name().expect("Can't get display name"))
}
}
impl fmt::Debug for Vector<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut debug_struct = f.debug_struct("Vector");
self.update_debug_struct(&mut debug_struct)
.field("export_config", &self.gen_env.get_export_config(self.entity()))
.field("element_type", &self.element_type())
.finish()
}
}