use syn::parse_quote;
use crate::composable::TypeModel;
use crate::composer::{SourceComposable, VarComposer};
use crate::context::ScopeContext;
use crate::kind::{DictFermentableModelKind, DictTypeModelKind, GroupModelKind, ObjectKind, ScopeItemKind, SmartPointerModelKind, SpecialType, TypeModelKind};
use crate::ext::{AsType, FFISpecialTypeResolve, GenericNestedArg, Resolve, ToType};
use crate::lang::{RustSpecification, Specification};
use crate::lang::rust::presentation::{resolve_type_variable_via_ffi_full_path, resolve_type_variable_via_maybe_object, resolve_type_variable_via_type};
use crate::presentation::{FFIFullPath, FFIVariable, ToFFIVariable};
impl SourceComposable for VarComposer<RustSpecification> {
type Source = ScopeContext;
type Output = <RustSpecification as Specification>::Var;
fn compose(&self, source: &Self::Source) -> Self::Output {
let search_key = self.search.search_key();
let ptr_composer = search_key.ptr_composer();
let maybe_obj = source.maybe_object_by_predicate_ref(&self.search);
let full_ty = maybe_obj
.as_ref()
.and_then(ObjectKind::maybe_type)
.unwrap_or_else(|| search_key.to_type());
let maybe_special = Resolve::<SpecialType<RustSpecification>>::maybe_resolve(&full_ty, source);
match maybe_special {
Some(special) => match maybe_obj {
Some(ObjectKind::Item(_, ScopeItemKind::Fn(..))) =>
ptr_composer(source.maybe_to_fn_type().unwrap_or_else(|| search_key.to_type())),
Some(ObjectKind::Item(TypeModelKind::FnPointer(..), ..) |
ObjectKind::Type(TypeModelKind::FnPointer(..), ..)) =>
special.to_direct_var(),
Some(ObjectKind::Item(TypeModelKind::Trait(..), ..) |
ObjectKind::Type(TypeModelKind::TraitType(..) |
TypeModelKind::Dictionary(DictTypeModelKind::LambdaFn(..)), ..)) => {
let ty = special.to_type();
ptr_composer(parse_quote!(dyn #ty))
},
Some(ObjectKind::Type(TypeModelKind::Bounds(bounds))) =>
bounds.resolve(source),
_ =>
ptr_composer(special.to_type())
}
None => {
match maybe_obj {
Some(ObjectKind::Item(.., ScopeItemKind::Fn(..))) =>
ptr_composer(source.maybe_to_trait_fn_type::<RustSpecification>().unwrap_or_else(|| search_key.to_type())),
Some(ObjectKind::Type(ref ty_model_kind)) |
Some(ObjectKind::Item(ref ty_model_kind, ..)) => {
let conversion = ty_model_kind.maybe_trait_object_maybe_model_kind_or_same(source);
match conversion {
TypeModelKind::Unknown(TypeModel { ty, .. }) =>
FFIVariable::mut_ptr(ty),
TypeModelKind::Dictionary(DictTypeModelKind::Primitive(TypeModel { ty, .. })) =>
ty.to_direct_var(),
TypeModelKind::Dictionary(DictTypeModelKind::NonPrimitiveFermentable(DictFermentableModelKind::I128(..) | DictFermentableModelKind::U128(..))) =>
FFIVariable::mut_ptr(parse_quote!([u8; 16])),
TypeModelKind::FnPointer(TypeModel { ty, .. }, ..) =>
Resolve::<SpecialType<RustSpecification>>::maybe_resolve(&ty, source)
.map(|special| special.to_type())
.unwrap_or_else(|| Resolve::<FFIFullPath<RustSpecification>>::resolve(&ty, source)
.to_type())
.to_direct_var(),
TypeModelKind::Dictionary(DictTypeModelKind::LambdaFn(TypeModel { ty, .. }, ..)) =>
FFIVariable::mut_ptr(Resolve::<FFIFullPath<RustSpecification>>::resolve(&ty, source).to_type()),
TypeModelKind::Dictionary(DictTypeModelKind::NonPrimitiveFermentable(DictFermentableModelKind::SmartPointer(SmartPointerModelKind::Box(model)))) |
TypeModelKind::Dictionary(DictTypeModelKind::NonPrimitiveFermentable(DictFermentableModelKind::Cow(model))) => {
let full_nested_ty = model.as_type().maybe_first_nested_type_ref().unwrap();
match Resolve::<SpecialType<RustSpecification>>::maybe_resolve(full_nested_ty, source) {
Some(special) => match source.maybe_object_by_value(full_nested_ty) {
Some(ObjectKind::Item(TypeModelKind::FnPointer(..), ..) |
ObjectKind::Type(TypeModelKind::FnPointer(..), ..)) =>
special.to_direct_var(),
Some(ObjectKind::Item(TypeModelKind::Trait(..), ..) |
ObjectKind::Type(TypeModelKind::TraitType(..), ..) |
ObjectKind::Type(TypeModelKind::Dictionary(DictTypeModelKind::LambdaFn(..)), ..)) => {
let ty = special.to_type();
ptr_composer(parse_quote!(dyn #ty))
},
_ => ptr_composer(special.to_type())
}
None => resolve_type_variable_via_maybe_object(source.maybe_object_by_value(full_nested_ty), full_nested_ty, source)
}
},
TypeModelKind::Dictionary(
DictTypeModelKind::NonPrimitiveFermentable(
DictFermentableModelKind::SmartPointer(
SmartPointerModelKind::Arc(TypeModel { ty, .. }) |
SmartPointerModelKind::Rc(TypeModel { ty, .. }) |
SmartPointerModelKind::Mutex(TypeModel { ty, .. }) |
SmartPointerModelKind::OnceLock(TypeModel { ty, .. }) |
SmartPointerModelKind::RwLock(TypeModel { ty, .. }) |
SmartPointerModelKind::Cell(TypeModel { ty, .. }) |
SmartPointerModelKind::RefCell(TypeModel { ty, .. }) |
SmartPointerModelKind::UnsafeCell(TypeModel { ty, .. }) |
SmartPointerModelKind::Pin(TypeModel { ty, .. })
) |
DictFermentableModelKind::Group(
GroupModelKind::BTreeSet(TypeModel { ty, .. }) |
GroupModelKind::HashSet(TypeModel { ty, .. }) |
GroupModelKind::Map(TypeModel { ty, .. }) |
GroupModelKind::Result(TypeModel { ty, .. }) |
GroupModelKind::Vec(TypeModel { ty, .. }) |
GroupModelKind::IndexMap(TypeModel { ty, .. }) |
GroupModelKind::IndexSet(TypeModel { ty, .. })
) |
DictFermentableModelKind::Other(TypeModel { ty, .. }) |
DictFermentableModelKind::Str(TypeModel { ty, .. }) |
DictFermentableModelKind::String(TypeModel { ty, .. }))) => {
resolve_type_variable_via_type(ty, source)
},
TypeModelKind::Dictionary(DictTypeModelKind::NonPrimitiveOpaque(..)) |
TypeModelKind::Bounds(..) =>
conversion.resolve(source),
ref cnv => {
if cnv.is_optional() {
if let Some(nested_ty) = full_ty.maybe_first_nested_type_kind() {
if let Some(special_ty) = FFISpecialTypeResolve::<RustSpecification>::maybe_custom_or_opaque(&nested_ty.to_type(), source) {
return FFIVariable::mut_ptr(special_ty.to_type());
}
}
}
maybe_obj.and_then(|obj|
obj.maybe_fn_or_trait_or_same_kind(source)
.map(|type_kind| resolve_type_variable_via_ffi_full_path(type_kind, source)))
.unwrap_or_else(|| resolve_type_variable_via_ffi_full_path(cnv.clone(), source))
}
}
},
_ => search_key.resolve(source)
}
}
}
}
}