extruct-macros 0.2.1

Implementation detail of the `extruct` crate. Use https://crates.io/crates/extruct in your code.
Documentation
use crate::extruct_from::Model;
use proc_macro2::TokenStream;
use quote::quote;

pub(crate) type Rust = TokenStream;

pub(crate) fn codegen(model: Model) -> Rust {
    let Model {
        substruct,
        superstruct_name,
        fields,
    } = model;

    let substruct_name = substruct.ident.clone();

    let assignments: Vec<_> = fields
        .into_iter()
        .map(|f| quote! { #f: value.#f.into()})
        .collect();

    quote!(

        #substruct

        impl std::convert::From<#superstruct_name> for #substruct_name {
            fn from(value: #superstruct_name) -> Self {
                Self {
                    #(#assignments,)*
                }
            }
        }

        impl extruct::ExtructedFrom<#superstruct_name> for #substruct_name {}
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use syn::{parse::Parse, parse_quote, ItemImpl, ItemStruct};
    struct StructDefAndImplBlock {
        struct_def: ItemStruct,
        #[allow(dead_code)]
        impl_blocks: [ItemImpl; 2],
    }

    impl Parse for StructDefAndImplBlock {
        fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
            let struct_def: ItemStruct = input.parse()?;
            let impl_block1: ItemImpl = input.parse()?;
            let impl_block2: ItemImpl = input.parse()?;
            Ok(Self {
                struct_def,
                impl_blocks: [impl_block1, impl_block2],
            })
        }
    }

    #[test]
    fn output_is_struct_def_and_impl_block() {
        let substruct: ItemStruct = parse_quote!(
            struct SomeStruct {
                first: String,
                second: u32,
            }
        );

        let model = Model {
            substruct: substruct.clone(),
            superstruct_name: parse_quote!(AnotherStruct),
            fields: vec![parse_quote!(first), parse_quote!(second)],
        };
        let rust = codegen(model);

        let parsed = syn::parse2::<StructDefAndImplBlock>(rust).unwrap();
        assert_eq!(parsed.struct_def, substruct);
    }
}