Untitled

 avatar
unknown
rust
a year ago
1.7 kB
10
Indexable
use std::collections::HashMap;
use syn::Ident;
use quote::quote;
use proc_macro2::TokenStream;

struct Module {
    name: Ident,
    content: Vec<TokenStream>,
    submodules: HashMap<String, Module>,
}

impl Module {
    fn new(name: &str) -> Self {
        Self {
            name: Ident::new(name, proc_macro2::Span::call_site()),
            content: Vec::new(),
            submodules: HashMap::new(),
        }
    }

    fn add_content(&mut self, content: TokenStream) {
        self.content.push(content);
    }

    fn get_or_create_submodule(&mut self, name: &str) -> &mut Module {
        if !self.submodules.contains_key(name) {
            self.submodules.insert(name.to_string(), Module::new(name));
        }
        self.submodules.get_mut(name).unwrap()
    }

    fn generate(&self) -> TokenStream {
        let name = &self.name;
        let content = &self.content;
        let submodules: Vec<TokenStream> = self.submodules.values().map(|m| m.generate()).collect();
        quote! {
            pub mod #name {
                #( #content )*
                #( #submodules )*
            }
        }
    }
}

struct ModuleComposer {
    root: Module,
}

impl ModuleComposer {
    fn new() -> Self {
        Self {
            root: Module::new("root"),
        }
    }

    fn add(&mut self, path: &str, content: TokenStream) {
        let mut current_module = &mut self.root;
        for name in path.split("::") {
            current_module = current_module.get_or_create_submodule(name);
        }
        current_module.add_content(content);
    }

    fn generate(&self) -> TokenStream {
        self.root.generate()
    }
}
Editor is loading...
Leave a Comment