ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use syn::Lifetime;
use crate::ast::{CommaParenWrapped, CommaPunctuated, Depunctuated, SemiPunctuated};
use crate::composable::FieldComposer;
use crate::composer::{AspectPresentable, AttrComposable, SourceComposable, GenericComposerInfo, ConversionFromComposer, ConversionToComposer, ConversionDropComposer, TupleComposer, VarComposer};
use crate::context::ScopeContext;
use crate::ext::{LifetimeProcessor, Mangle};
use crate::kind::FieldTypeKind;
use crate::lang::{NameComposable, RustSpecification, Specification};
use crate::presentable::{Aspect, Expression, ScopeContextPresentable};
use crate::presentation::{DictionaryExpr, InterfacePresentation};

impl SourceComposable for TupleComposer<RustSpecification> {
    type Source = ScopeContext;
    type Output = Option<GenericComposerInfo<RustSpecification>>;

    fn compose(&self, source: &Self::Source) -> Self::Output {
        let mut lifetimes = Vec::<Lifetime>::new();
        let ffi_type = self.present_ffi_aspect();
        let types = (ffi_type.clone(), self.present_target_aspect());
        let name = self.type_tuple.mangle_ident_default();
        let mut from_conversions = CommaPunctuated::new();
        let mut to_conversions = CommaPunctuated::new();
        let mut destroy_conversions = SemiPunctuated::new();
        let mut field_composers = Depunctuated::new();
        self.type_tuple
            .elems
            .iter()
            .enumerate()
            .for_each(|(index, ty)| {
                lifetimes.extend(ty.unique_lifetimes());
                let name = <RustSpecification as Specification>::Name::unnamed_arg(index);
                let from_composer = ConversionFromComposer::<RustSpecification>::value_ref_expr(&name, ty, Expression::ffi_ref_with_name(&name));
                let to_composer = ConversionToComposer::<RustSpecification>::value_ref_expr(&name, ty, Expression::ObjName(<RustSpecification as Specification>::Name::index(index)));
                let drop_composer = ConversionDropComposer::<RustSpecification>::value_ref_expr(&name, ty, Expression::dict_expr(DictionaryExpr::self_prop(&name)));
                from_conversions.push(from_composer.compose(source).present(source));
                to_conversions.push(Expression::named(&name, to_composer.compose(source)).present(source));
                if let Some(drop_conversion) = drop_composer.compose(source) {
                    destroy_conversions.push(drop_conversion.present(source));
                }
                field_composers.push(FieldComposer::unnamed(name, FieldTypeKind::Var(VarComposer::<RustSpecification>::key_ref_in_composer_scope(ty).compose(source))));
            });
        let attrs = self.compose_attributes();
        let interfaces = Depunctuated::from_iter([
            InterfacePresentation::conversion_from_root(&attrs, &types, CommaParenWrapped::new(from_conversions), &None, &lifetimes),
            InterfacePresentation::conversion_to_boxed_self_destructured(&attrs, &types, to_conversions, &None, &lifetimes),
            InterfacePresentation::drop(&attrs, ffi_type, destroy_conversions)
        ]);
        Some(GenericComposerInfo::<RustSpecification>::default(Aspect::raw_struct_ident(name), &attrs, field_composers, interfaces))
    }
}