torn-api-codegen 0.8.1

Contains the v2 torn API model descriptions and codegen for the bindings
Documentation
use heck::ToUpperCamelCase;
use indexmap::IndexMap;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};

use super::path::{Path, PathSegment};

pub struct Scope {
    pub name: String,
    pub mod_name: String,
    pub members: Vec<Path>,
}

impl Scope {
    pub fn from_paths(paths: Vec<Path>) -> Vec<Scope> {
        let mut map = IndexMap::new();

        for path in paths {
            let Some(PathSegment::Constant(first_seg)) = path.segments.first() else {
                continue;
            };

            map.entry(first_seg.to_owned())
                .or_insert_with(|| Scope {
                    name: format!("{}Scope", first_seg.to_upper_camel_case()),
                    mod_name: first_seg.clone(),
                    members: Vec::new(),
                })
                .members
                .push(path);
        }

        map.into_values().collect()
    }

    pub fn codegen(&self) -> Option<TokenStream> {
        let name = format_ident!("{}", self.name);
        let bulk_name = format_ident!("Bulk{}", self.name);

        let mut functions = Vec::with_capacity(self.members.len());
        let mut bulk_functions = Vec::with_capacity(self.members.len());

        for member in &self.members {
            if let Some(code) = member.codegen_scope_call() {
                functions.push(code);
            }
            if let Some(code) = member.codegen_bulk_scope_call() {
                bulk_functions.push(code);
            }
        }

        Some(quote! {
            #[allow(dead_code)]
            pub struct #name<E>(E)
            where
                E: crate::executor::Executor;

            impl<E> #name<E>
            where
                E: crate::executor::Executor
            {
                pub fn new(executor: E) -> Self {
                    Self(executor)
                }

                #(#functions)*
            }

            #[allow(dead_code)]
            pub struct #bulk_name<E> where
                E: crate::executor::BulkExecutor,
            {
                executor: E,
            }

            impl<E> #bulk_name<E>
            where
                E: crate::executor::BulkExecutor
            {
                pub fn new(executor: E) -> Self {
                    Self {
                        executor,
                    }
                }

                #(#bulk_functions)*
            }
        })
    }
}