bogie_derive 0.1.3

Macro crate for bogie
Documentation
use darling::{FromDeriveInput, FromField, FromMeta};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Path};

#[derive(Debug, Clone, FromDeriveInput)]
#[darling(attributes(bogie))]
pub struct GlobalOptions {
    #[darling(default)]
    pub pub_only: bool,
    #[darling(default)]
    pub enum_prefix: bool,
    #[darling(flatten)]
    pub options: Options
}

#[derive(Debug, Clone, FromField)]
#[darling(attributes(bogie))]
pub struct FieldOptions {
    #[darling(flatten)]
    pub options: Options
}

#[derive(Debug, Clone, FromMeta)]
#[darling(and_then = Options::check)]
pub struct Options {
    #[darling(default)]
    pub skip: bool,
    #[darling(rename = "dbg", default)]
    pub debug: bool,
    #[darling(rename = "display", default)]
    pub display: bool,
    #[darling(rename = "Hex", default)]
    pub upper_hex: bool,
    #[darling(rename = "hex", default)]
    pub lower_hex: bool,
    #[darling(rename = "oct", default)]
    pub octal: bool,
    #[darling(rename = "ptr", default)]
    pub pointer: bool,
    #[darling(rename = "Exp", default)]
    pub upper_exp: bool,
    #[darling(rename = "exp", default)]
    pub lower_exp: bool,
    #[darling(rename = "bin", default)]
    pub binary: bool,
    #[darling(rename = "empty", default)]
    pub empty: bool,
    #[darling(rename = "fn", default)]
    pub fn_path: Option<Path>
}

impl Options {
    fn sum(&self) -> usize {
        self.skip as usize +
            self.debug as usize +
            self.display as usize +
            self.upper_hex as usize +
            self.lower_hex as usize +
            self.binary as usize +
            self.empty as usize +
            self.octal as usize +
            self.pointer as usize +
            self.upper_exp as usize +
            self.lower_exp as usize +
            self.fn_path.is_some() as usize
    }

    fn check(self) -> darling::Result<Self> {
        if self.sum() > 1 {
            Err(darling::Error::too_many_items(1))
        } else {
            Ok(self)
        }
    }

    pub fn into_formatter(self) -> Option<Formatter> {
        if self.skip {
            unreachable!()
        } else if self.debug {
            Some(Formatter::Debug)
        } else if self.display {
            Some(Formatter::Display)
        } else if self.upper_hex {
            Some(Formatter::UpperHex)
        } else if self.lower_hex {
            Some(Formatter::LowerHex)
        } else if self.octal {
            Some(Formatter::Octal)
        } else if self.pointer {
            Some(Formatter::Pointer)
        } else if self.upper_exp {
            Some(Formatter::UpperExp)
        } else if self.lower_exp {
            Some(Formatter::LowerExp)
        } else if self.binary {
            Some(Formatter::Binary)
        } else if self.empty {
            Some(Formatter::Empty)
        } else if let Some(p) = self.fn_path {
            Some(Formatter::FnPath(p))
        } else {
            None
        }
    }
}

#[derive(Clone, Debug)]
pub enum Formatter {
    Debug,
    Display,
    UpperHex,
    LowerHex,
    Octal,
    Pointer,
    UpperExp,
    LowerExp,
    Binary,
    Empty,
    FnPath(Path)
}


impl Formatter {
    pub fn as_dyn_debug(&self, field_tokens: TokenStream) -> TokenStream {
        match self {
            Formatter::Debug => {
                quote! {
                    &#field_tokens
                }
            }
            Formatter::Display => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::Display::fmt(&#field_tokens, f))
                }
            }
            Formatter::UpperHex => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::UpperHex::fmt(&#field_tokens, f))
                }
            }
            Formatter::LowerHex => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::LowerHex::fmt(&#field_tokens, f))
                }
            }
            Formatter::Octal => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::Octal::fmt(&#field_tokens, f))
                }
            }
            Formatter::Pointer => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::Pointer::fmt(&#field_tokens, f))
                }
            }
            Formatter::UpperExp => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::UpperExp::fmt(&#field_tokens, f))
                }
            }
            Formatter::LowerExp => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::LowerExp::fmt(&#field_tokens, f))
                }
            }
            Formatter::Binary => {
                quote! {
                    &bogie::FnFormat(|f| core::fmt::Binary::fmt(&#field_tokens, f))
                }
            }
            Formatter::Empty => {
                quote! {
                    &()
                }
            }
            Formatter::FnPath(p) => {
                quote! {
                    &bogie::FnFormat(|f| #p(&#field_tokens, f))
                }
            }
        }
    }
}