nesting 0.1.1

Nesting structs, enums, and impls, in Rust!
Documentation
//! # Nested Structs & Enums
//! This crate allows you to nest structs, enums, and impls, in a way that is similar to how it's done in Zig.
//!
//! # Examples
//!
//! ```rust
//!
//! nesting::nest! {
//!     // #![] attributes apply to all structs and enums in the nest!{} block.
//!     #![derive(Debug)]
//!     // Becomes:
//!     // #![structs(allow(dead_code))]
//!     // #![enums(allow(dead_code))]
//!
//!     // You can also scope the attributes like so:
//!     #![all(allow(dead_code))] // using `all` means it will also apply to `impl`s!
//!     // Which is the same as:
//!     // #![structs(allow(dead_code))]
//!     // #![enums(allow(dead_code))]
//!     // #![impls(allow(dead_code))]
//!
//!     pub struct MarkerStruct;
//!
//!     struct TupleStruct(String, u32);
//!
//!     struct FieldStruct {
//!         field1: String,
//!         field2: u32
//!         child: ChildStruct,
//!         my_enum: Enum
//!
//!         // Loose functions get put into impl StructName {} blocks.
//!         // i.e. this would be impl FieldStruct { pub fn my_fn() {} }
//!         pub fn some_struct_fn(&self) {
//!             println!("This function is nested inside the struct!");
//!         }
//!
//!         // You can add attributes to individual structs/enums/impls as usual
//!         #[derive(Clone, Hash)]
//!         struct ChildStruct {
//!             field1: String,
//!             field2: u32,
//!             child: ChildChildStruct
//!
//!             // You can nest infinitely...
//!             #[derive(Clone, Hash)]
//!             struct ChildChildStruct;
//!         }
//!
//!         impl ChildStruct {
//!             pub fn some_impl_fn(&self) {
//!                 println!("This function is nested inside struct->impl");
//!             }
//!         }
//!
//!         // We can impl Foo for Bar
//!         impl std::fmt::Display for ChildStruct {
//!             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
//!                 write!(f, "{}: {}", &self.field1, self.field2)
//!             }
//!         }
//!
//!         // We can make enums too
//!         enum Enum {
//!             A,
//!             B(String),
//!             C {
//!                 a: String,
//!                 b: u64,
//!             }
//!
//!             // Nesting works just fine in enums
//!             #[derive(Default)]
//!             struct StructInsideEnum(String);
//!
//!             enum Enum2 { A, B, C }
//!
//!             pub fn some_enum_fn(&self) {
//!                 println!("This is a function inside an enum!");
//!             }
//!         }
//!     }
//! }
//! ```

mod parser;

use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;

/// Create nested structs, enums, and impls.
///
/// # Examples
///
/// ```rust
/// nesting::nest! {
///     struct MyStruct {
///         child: MyChildStruct
///
///         struct MyChildStruct {
///             is_nested: bool,
///
///             impl Default for MyChildStruct {
///                 fn default() -> Self {
///                     Self { is_nested: true}
///                 }
///             }
///         }
///     }
/// }
/// ```
#[proc_macro]
pub fn nest(input: TokenStream) -> TokenStream {
    let nest_input = parse_macro_input!(input as parser::NestInput);

    let mut all_items = Vec::new();

    for item_def in nest_input.items {
        all_items.extend(item_def.flatten());
    }

    let generated_code = all_items.iter().map(|s| {
        let global_attrs = &nest_input.global_attrs;

        s.render(global_attrs)
    });

    let result = quote! {
        #(#generated_code)*
    };

    result.into()
}