serde_int_map_derive 0.1.2

Deriviation of serde Serialize and Deserialize for maps indexed by integers
Documentation
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};

use crate::{parser_helper, CatchallType};

pub(crate) fn impl_derive_serialize_int_map(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let ident = input.ident;

    let fields = match input.data {
        Data::Struct(data) => match data.fields {
            Fields::Named(fields) => fields.named,
            _ => panic!("Serialize_Int_Map applied to invalid struct type"),
        },
        _ => panic!("Serialize_Int_Map applied to invalid type"),
    };

    let quotes_list = fields
        .iter()
        .map(|field| {
            let ident = field.ident.as_ref().expect("No identifier");
            let (_, is_optional) = parser_helper::get_field_type_and_optionality(field);

            let (attr_key, catchall_type) =
                parser_helper::get_field_matcher_and_catchall_type(field);

            let attr_counter = if catchall_type.is_some() {
                quote! { + self.#ident.num_items() }
            } else {
                /* A field that's not catchall, has 1 value */
                quote! { + 1 }
            };

            let attr_serializer = match catchall_type {
                None => {
                    if is_optional {
                        quote! {
                            if let Some(value) = &self.#ident {
                                map.serialize_entry(&#attr_key, &value)?;
                            }
                        }
                    } else {
                        quote! {
                            map.serialize_entry(&#attr_key, &self.#ident)?;
                        }
                    }
                }
                Some(CatchallType::Fields) => {
                    panic!("TODO: CatchallType::Fields implementation");
                }
                Some(CatchallType::Unknown) => {
                    quote! {
                        for (k, v) in self.#ident.iter() {
                            map.serialize_entry(k, v)?;
                        }
                    }
                }
            };

            (attr_counter, attr_serializer)
        })
        .collect::<Vec<(_, _)>>();
    let (attr_counters, attr_serializers) = crate::utils::list_to_tuple_2(quotes_list);

    let res = TokenStream::from(quote! {
        impl serde::Serialize for #ident {
            fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                use serde::ser::SerializeMap;
                use serde_int_map::UnknownKeyHandler;

                let count = 0
                    #(#attr_counters)*
                ;

                let mut map = serializer.serialize_map(Some(count))?;
                #(#attr_serializers)*
                map.end()
            }
        }
    });

    #[cfg(feature = "print_tokenstreams")]
    println!("Serialization tokenstream for {}: {}", ident, res);

    res
}