ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use std::marker::PhantomData;
use quote::ToTokens;
use syn::token::{Brace, Comma, Paren, Semi};
use crate::ast::{DelimiterTrait, Void};
use crate::composable::FieldComposer;
use crate::composer::{AspectSeqKindComposer, AttrComposable, ComposerLink, PresentableArgKindPairComposerRef, ConversionSeqKindComposer, DropSeqKindComposer, FFIBindingsComposer, FFIComposer, ArgProducerByRef, FieldPathResolver, FieldsComposerRef, FieldsContext, FieldsConversionComposable, FieldsOwnedSequenceComposer, FieldsOwnedSequenceComposerLink, GenericsComposable, MaybeSequenceOutputComposer, NameKindComposable, OwnerAspectSequenceComposer, OwnerAspectSequenceSpecComposer, ArgKindPair, PresentableExprComposerRef, SequenceComposer, SharedAspectArgComposer, SourceAccessible, TypeAspect, PresentableArgsSequenceComposer, IterativeComposer, FFIInterfaceMethodIterator, ArgKindProducerByRef, FieldComposerProducer, OwnerAspect, OwnedArgComposers, CommaPunctuatedArgKinds, OwnerAspectSequence, constants, AspectArgSourceComposer, LifetimesComposable, CtorSequenceComposer};
use crate::lang::Specification;
use crate::presentable::{ArgKind, Aspect, BindingPresentableContext, Expression, ScopeContextPresentable, SeqKind};
use crate::shared::SharedAccess;

pub trait FFIObjectSpec<SPEC, L>
    where L: SharedAccess,
          SPEC: Specification {
    const COMPOSER: MaybeSequenceOutputComposer<SPEC, L>;
}

pub trait FFIConversionsSpec<SPEC, L>
    where SPEC: Specification,
          L: SharedAccess {
    const COMPOSER: Option<FFIComposer<SPEC, L>>;
}
pub trait FFIBindingsSpec<SPEC, L, Iter>
    where SPEC: Specification,
          L: SharedAccess,
          Iter: FromIterator<Iter::Item> + IntoIterator<Item=ArgKindPair<SPEC>> +  {
    const COMPOSER: Option<FFIBindingsComposer<SPEC, L, Iter>>;
}

#[allow(unused)]
pub trait OwnerAspectSequenceSpec<SPEC, L, Iter, IterMap, Out>
    where SPEC: Specification,
          L: SharedAccess,
          Iter: FromIterator<Iter::Item> + IntoIterator<Item=IterMap> {
    const ROOT: OwnerAspectSequenceComposer<SPEC, Iter, Out>;
    const ASPECT: SharedAspectArgComposer<SPEC, L>;
    const ITER: AspectArgSourceComposer<SPEC, Iter>;
    const ARG: ArgProducerByRef<SPEC, Iter::Item>;
    const COMPOSER: OwnerAspectSequenceSpecComposer<SPEC, L, Iter, Out> =
        SequenceComposer::with_iterator_setup(Self::ROOT, Self::ASPECT, Self::ITER, Self::ARG);
}
pub trait CtorSpec<SPEC, L, Iter>
    where SPEC: Specification,
          L: SharedAccess,
          Iter: IntoIterator<Item=ArgKindPair<SPEC>> {
    const ROOT: OwnerAspectSequenceComposer<SPEC, Iter, BindingPresentableContext<SPEC>>;
    const ASPECT: SharedAspectArgComposer<SPEC, L>;
    const ARG: PresentableArgKindPairComposerRef<SPEC>;
    const ITER: AspectArgSourceComposer<SPEC, Iter>;
    const COMPOSER: CtorSequenceComposer<SPEC, L, Iter> =
        SequenceComposer::with_iterator_setup(Self::ROOT, Self::ASPECT, Self::ITER, Self::ARG);
}

pub trait FieldSpec<SPEC>
    where SPEC: Specification {
    const FIELD_PRODUCER: ArgKindProducerByRef<SPEC>;
    const PRODUCIBLE_FIELDS: IterativeComposer<OwnedArgComposers<SPEC, OwnerAspect<SPEC>>, FieldComposer<SPEC>, ArgKind<SPEC>, OwnerAspectSequence<SPEC, CommaPunctuatedArgKinds<SPEC>>> =
        IterativeComposer::aspect_fields(Self::FIELD_PRODUCER);
}

pub trait FieldNameSpec<SPEC>
    where SPEC: Specification {
    const COMPOSER: FieldComposerProducer<SPEC>;
    const FIELDS: FieldsComposerRef<SPEC> =
        |fields| constants::field_composers_iterator(fields, Self::COMPOSER);
}

pub trait FFIFieldsSpec<SPEC, L>
    where SPEC: Specification,
          L: SharedAccess {
    const FROM: FieldsOwnedSequenceComposer<SPEC, L>;
    const TO: FieldsOwnedSequenceComposer<SPEC, L>;
}

impl<SPEC, T, C> FFIFieldsSpec<SPEC, ComposerLink<T>> for C
    where SPEC: Specification,
          T: AttrComposable<SPEC::Attr>
              + GenericsComposable<SPEC::Gen>
              + LifetimesComposable<SPEC::Lt>
              + TypeAspect<SPEC::TYC>
              + NameKindComposable
              + FieldsContext<SPEC>
              + FieldsConversionComposable<SPEC>
              + SourceAccessible
              + 'static,
          C: ItemComposerSpec<SPEC> + FieldSpec<SPEC> {
    const FROM: FieldsOwnedSequenceComposerLink<SPEC, T> =
        SequenceComposer::item_field_from_spec::<C>(Aspect::ffi);
    const TO: FieldsOwnedSequenceComposerLink<SPEC, T> =
        SequenceComposer::item_field_to_spec::<C>(Aspect::target);
}

pub trait ItemComposerSpec<SPEC>
    where SPEC: Specification {
    const FROM_ROOT_PRESENTER: PresentableArgsSequenceComposer<SPEC>;
    const TO_ROOT_PRESENTER: PresentableArgsSequenceComposer<SPEC>;
    const FROM_ROOT_CONVERSION_PRESENTER: ConversionSeqKindComposer<SPEC>;
    const TO_ROOT_CONVERSION_PRESENTER: ConversionSeqKindComposer<SPEC>;
    const DROP_ROOT_CONVERSION_PRESENTER: DropSeqKindComposer<SPEC>;
    const FIELD_COMPOSERS: FieldsComposerRef<SPEC>;
}

pub trait FieldPathConversionResolveSpec<SPEC>
    where SPEC: Specification {
    const FROM: FieldPathResolver<SPEC>;
    const TO: FieldPathResolver<SPEC>;
    const DROP: FieldPathResolver<SPEC>;
}

#[allow(unused)]
pub trait FFIInterfaceMethodSpec<SPEC, SEP>
    where SPEC: Specification,
          SEP: ToTokens + Default {
    const RESOLVER: FieldPathResolver<SPEC>;
    const SEQ: AspectSeqKindComposer<SPEC, SEP>;
    const EXPR: PresentableExprComposerRef<SPEC>;
    const ITER: FFIInterfaceMethodIterator<SPEC, SEP> =
        IterativeComposer::aspect_sequence_expr::<Self, SEP>();
}

pub trait ItemComposerExprSpec<SPEC>
    where SPEC: Specification {
    const FROM_CONVERSION: PresentableExprComposerRef<SPEC>;
    const TO_CONVERSION: PresentableExprComposerRef<SPEC>;
    const DROP_CONVERSION: PresentableExprComposerRef<SPEC>;
}

#[allow(unused)]
pub trait ItemAspectsSpec<SPEC>
    where SPEC: Specification {
    // type CTOR: FFIInterfaceMethodSpec<SPEC, Comma>
    //     + AttrComposable<SPEC::Attr>
    //     + GenericsComposable<SPEC::Gen>
    //     + TypeAspect<SPEC::TYC>
    //     + FieldsContext<SPEC>
    //     + NameKindComposable;
    type DTOR: FFIInterfaceMethodSpec<SPEC, Semi>;
    type FROM: FFIInterfaceMethodSpec<SPEC, Comma>;
    type INTO: FFIInterfaceMethodSpec<SPEC, Comma>;
}

#[allow(unused)]
pub struct FromStub<I: DelimiterTrait + 'static>(PhantomData<I>);
pub struct ToStub<I: DelimiterTrait + 'static>(PhantomData<I>);
pub struct DropStub<I: DelimiterTrait + 'static>(PhantomData<I>);

#[allow(unused)]
pub struct FromStrategy<I: DelimiterTrait + 'static>(PhantomData<I>);
#[allow(unused)]
pub struct ToStrategy<I: DelimiterTrait + 'static>(PhantomData<I>);
#[allow(unused)]
pub struct DropStrategy<I: DelimiterTrait + 'static>(PhantomData<I>);

impl<SPEC> FFIInterfaceMethodSpec<SPEC, Comma> for FromStrategy<Brace>
where SPEC: Specification<Expr=Expression<SPEC>>,
      Self: FieldPathConversionResolveSpec<SPEC>,
      SPEC::Expr: ScopeContextPresentable {
    const RESOLVER: FieldPathResolver<SPEC> =
        Self::FROM;
    const SEQ: AspectSeqKindComposer<SPEC, Comma> =
        SeqKind::FromNamedFields;
    const EXPR: PresentableExprComposerRef<SPEC> =
        SPEC::Expr::named_conversion;
}

impl<SPEC> FFIInterfaceMethodSpec<SPEC, Comma> for FromStrategy<Paren>
where SPEC: Specification<Expr=Expression<SPEC>>,
      Self: FieldPathConversionResolveSpec<SPEC>,
      SPEC::Expr: ScopeContextPresentable {
    const RESOLVER: FieldPathResolver<SPEC> =
        Self::FROM;
    const SEQ: AspectSeqKindComposer<SPEC, Comma> =
        SeqKind::FromUnnamedFields;
    const EXPR: PresentableExprComposerRef<SPEC> =
        SPEC::Expr::bypass;
}
impl<SPEC> FFIInterfaceMethodSpec<SPEC, Comma> for FromStrategy<Void>
where SPEC: Specification<Expr=Expression<SPEC>>,
      Self: FieldPathConversionResolveSpec<SPEC>,
      SPEC::Expr: ScopeContextPresentable {
    const RESOLVER: FieldPathResolver<SPEC> =
        Self::FROM;
    const SEQ: AspectSeqKindComposer<SPEC, Comma> =
        SeqKind::no_fields;
    const EXPR: PresentableExprComposerRef<SPEC> =
        SPEC::Expr::bypass;
}