ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use std::fmt::Debug;
use proc_macro2::Ident;
use quote::ToTokens;
use syn::Type;
use ferment_macro::Display;
use crate::ast::CommaPunctuated;
use crate::composer::{AspectCommaPunctuatedArgKinds, AttrComposable, TypeAspect, VariantComposable, FieldsConversionComposable, SourceComposable, ComposerLinkRef, AspectTerminatedArgKinds, AspectPresentableArgKinds, CommaPunctuatedArgKinds};
use crate::lang::Specification;
use crate::presentable::Aspect;


#[derive(Clone, Debug, Display)]
pub enum SeqKind<SPEC>
    where SPEC: Specification {
    FromStub(AspectCommaPunctuatedArgKinds<SPEC>),
    FromNamedFields(AspectCommaPunctuatedArgKinds<SPEC>),
    ToNamedFields(AspectCommaPunctuatedArgKinds<SPEC>),
    FromUnnamedFields(AspectCommaPunctuatedArgKinds<SPEC>),
    TraitImplFnCall(((Type, Type, Ident), CommaPunctuatedArgKinds<SPEC>)),
    ToUnnamedFields(AspectCommaPunctuatedArgKinds<SPEC>),
    ToStub(AspectCommaPunctuatedArgKinds<SPEC>),
    NamedVariantFields(AspectCommaPunctuatedArgKinds<SPEC>),
    UnnamedVariantFields(AspectCommaPunctuatedArgKinds<SPEC>),
    EnumUnitFields(AspectCommaPunctuatedArgKinds<SPEC>),

    Variants(Aspect<SPEC::TYC>, SPEC::Attr, CommaPunctuated<SeqKind<SPEC>>),
    Unit(Aspect<SPEC::TYC>),
    NoFieldsConversion(Aspect<SPEC::TYC>),
    TypeAliasFromConversion(AspectCommaPunctuatedArgKinds<SPEC>),
    NamedStruct(AspectCommaPunctuatedArgKinds<SPEC>),
    UnnamedStruct(AspectCommaPunctuatedArgKinds<SPEC>),
    StubStruct(AspectCommaPunctuatedArgKinds<SPEC>),
    Enum(Box<SeqKind<SPEC>>),

    StructFrom(Box<SeqKind<SPEC>>, Box<SeqKind<SPEC>>),
    StructTo(Box<SeqKind<SPEC>>, Box<SeqKind<SPEC>>),

    EnumVariantFrom(Box<SeqKind<SPEC>>, Box<SeqKind<SPEC>>),
    EnumVariantTo(Box<SeqKind<SPEC>>, Box<SeqKind<SPEC>>),
    EnumVariantDrop(Box<SeqKind<SPEC>>, Box<SeqKind<SPEC>>),

    DerefFFI,
    Obj,
    Empty,

    DropStub(AspectTerminatedArgKinds<SPEC>),
    StructDropBody(AspectTerminatedArgKinds<SPEC>),
    DropCode(AspectTerminatedArgKinds<SPEC>),
}

impl<SPEC> SeqKind<SPEC>
    where SPEC: Specification {
    pub fn struct_to(field_path: &SeqKind<SPEC>, conversions: SeqKind<SPEC>) -> Self {
        Self::StructTo(field_path.clone().into(), conversions.into())
    }
    pub fn struct_from(field_path: &SeqKind<SPEC>, conversions: SeqKind<SPEC>) -> Self {
        Self::StructFrom(field_path.clone().into(), conversions.into())
    }
    pub fn variant_from(left: &SeqKind<SPEC>, right: SeqKind<SPEC>) -> Self {
        Self::EnumVariantFrom(left.clone().into(), right.clone().into())
    }
    pub fn variant_to(left: &SeqKind<SPEC>, right: SeqKind<SPEC>) -> Self {
        Self::EnumVariantTo(left.clone().into(), right.clone().into())
    }
    pub fn variant_drop(left: &SeqKind<SPEC>, right: SeqKind<SPEC>) -> Self {
        Self::EnumVariantDrop(left.clone().into(), right.clone().into())
    }
    pub fn struct_drop_post_processor(_: &SeqKind<SPEC>, right: SeqKind<SPEC>) -> Self {
        right
    }

    pub fn no_fields<SEP: ToTokens>(((aspect, ..), _): AspectPresentableArgKinds<SPEC, SEP>) -> Self {
        Self::NoFieldsConversion(match &aspect {
            Aspect::Target(context) => Aspect::RawTarget(context.clone()),
            _ => aspect.clone(),
        })
    }
    pub fn unit(((aspect, ..), _): &AspectCommaPunctuatedArgKinds<SPEC>) -> Self {
        Self::Unit(aspect.clone())
    }
    pub fn variants<C>(composer_ref: &ComposerLinkRef<C>) -> Self
        where C: AttrComposable<SPEC::Attr> + TypeAspect<SPEC::TYC> + VariantComposable<SPEC> {
        Self::Variants(C::target_type_aspect(composer_ref), C::compose_attributes(composer_ref), C::compose_variants(composer_ref))
    }
    pub fn deref_ffi<C>(_ctx: &ComposerLinkRef<C>) -> Self {
        Self::DerefFFI
    }
    pub fn empty<C>(_ctx: &ComposerLinkRef<C>) -> Self {
        Self::Empty
    }
    pub fn obj<C>(_ctx: &ComposerLinkRef<C>) -> Self {
        Self::Obj
    }
    pub fn unit_fields(context: &AspectCommaPunctuatedArgKinds<SPEC>) -> Self {
        Self::EnumUnitFields(context.clone())
    }
    pub fn brace_variants(context: &AspectCommaPunctuatedArgKinds<SPEC>) -> Self {
        Self::NamedVariantFields(context.clone())
    }
    pub fn paren_variants(context: &AspectCommaPunctuatedArgKinds<SPEC>) -> Self {
        Self::UnnamedVariantFields(context.clone())
    }
    pub fn empty_root(_: SeqKind<SPEC>) -> Self {
        Self::Empty
    }
    pub fn bypass(sequence: SeqKind<SPEC>) -> Self {
        sequence
    }
    pub fn r#enum(context: SeqKind<SPEC>) -> Self {
        Self::Enum(Box::new(context))
    }
    pub fn fields_from<C>(ctx: &ComposerLinkRef<C>) -> Self
        where C: FieldsConversionComposable<SPEC> + 'static {
        ctx.fields_from().compose(&())
    }
    pub fn fields_to<C>(ctx: &ComposerLinkRef<C>) -> Self
        where C: FieldsConversionComposable<SPEC> + 'static {
        ctx.fields_to().compose(&())
    }
}