accepts-codegen 0.0.1

Rust toolkit for composing synchronous and asynchronous acceptor pipelines
Documentation
use std::hash::RandomState;

use syn::{
    AngleBracketedGenericArguments, Attribute, Generics, ImplItem, ItemImpl, Path, PathArguments,
    Token, Type, TypePath,
    token::{self, Brace, For, Impl, PathSep},
};

use crate::common::syn::{
    ast::{function::merge_generics, tokens::PathSplitLastArgs, util::generic::param_to_argument},
    ext::AngleBracketedGenericArgumentsConstructExt,
};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PartialTraitImpl {
    pub attrs: Vec<Attribute>,
    pub defaultness: Option<Token![default]>,
    pub unsafety: Option<Token![unsafe]>,
    pub impl_token: Token![impl],
    pub generics: Generics,
    pub trait_: (Option<Token![!]>, Path, Token![for]),
    pub brace_token: token::Brace,
    pub items: Vec<ImplItem>,
}

#[allow(dead_code)]
impl PartialTraitImpl {
    pub fn from_parts(
        attrs: Vec<Attribute>,
        defaultness: Option<Token![default]>,
        unsafety: Option<Token![unsafe]>,
        impl_token: Token![impl],
        generics: Generics,
        trait_: (Option<Token![!]>, Path, Token![for]),
        brace_token: token::Brace,
        items: Vec<ImplItem>,
    ) -> Self {
        Self {
            attrs,
            defaultness,
            unsafety,
            impl_token,
            generics,
            trait_,
            brace_token,
            items,
        }
    }

    pub fn from_trait_path(trait_path: Path) -> Self {
        Self::from_parts(
            Vec::new(),
            None,
            None,
            Impl::default(),
            Generics::default(),
            (None, trait_path, For::default()),
            Brace::default(),
            Vec::new(),
        )
    }

    pub fn into_item_impl(
        self,
        self_ty_path: PathSplitLastArgs,
        self_ty_generics: Generics,
    ) -> ItemImpl {
        let self_ty_generics_params = self_ty_generics.params.clone();
        let self_ty_generics_lt_token = self_ty_generics.lt_token.clone();
        let self_ty_generics_gt_token = self_ty_generics.gt_token.clone();

        ItemImpl {
            attrs: self.attrs,
            defaultness: self.defaultness,
            unsafety: self.unsafety,
            impl_token: self.impl_token,
            generics: merge_generics::<RandomState>(self_ty_generics, self.generics),
            trait_: Some(self.trait_),
            self_ty: Box::new(Type::Path(TypePath {
                qself: None,
                path: {
                    self_ty_path.into_path(if self_ty_generics_params.is_empty() {
                        PathArguments::None
                    } else {
                        PathArguments::AngleBracketed(AngleBracketedGenericArguments::from_parts(
                            Some(PathSep::default()),
                            self_ty_generics_lt_token.unwrap_or_default(),
                            self_ty_generics_params
                                .into_iter()
                                .map(param_to_argument)
                                .collect(),
                            self_ty_generics_gt_token.unwrap_or_default(),
                        ))
                    })
                },
            })),
            brace_token: self.brace_token,
            items: self.items,
        }
    }

    pub fn decompose_and_restore<Inspector>(
        self,
        self_ty_path: PathSplitLastArgs,
        self_ty_generics: Generics,
        inspector: Inspector,
    ) -> Self
    where
        Inspector: FnOnce(&ItemImpl),
    {
        let generics_backup = self.generics.clone();

        let item_impl = self.into_item_impl(self_ty_path, self_ty_generics);

        (inspector)(&item_impl);

        Self::from_parts(
            item_impl.attrs,
            item_impl.defaultness,
            item_impl.unsafety,
            item_impl.impl_token,
            generics_backup,
            item_impl.trait_.unwrap(),
            item_impl.brace_token,
            item_impl.items,
        )
    }
}