line-protocol-derive 0.1.0

Implementation of Influx's line protocol (derive macros)
Documentation
use proc_macro2::Literal;
use quote::{ToTokens, format_ident, quote};

pub enum GeneratorMember {
    Named(String),
    Unnamed(usize),
}

impl ToTokens for GeneratorMember {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        tokens.extend(match self {
            GeneratorMember::Named(s) => {
                let s = format_ident!("{}", s);
                quote!(self.#s)
            }
            GeneratorMember::Unnamed(n) => {
                let n = Literal::usize_unsuffixed(*n);
                quote!(self.#n)
            }
        })
    }
}

pub struct GeneratorMeasurement {
    pub name: String,
}

impl ToTokens for GeneratorMeasurement {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let name = &self.name;

        tokens.extend(quote!(
            .measurement(#name)
        ))
    }
}

pub struct GeneratorTag {
    pub name: String,
    pub member: GeneratorMember,
}

impl ToTokens for GeneratorTag {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let name = &self.name;
        let member = &self.member;

        tokens.extend(quote!(
            .tag(#name, &#member)
        ))
    }
}

pub struct GeneratorField {
    pub name: String,
    pub member: GeneratorMember,
}

impl ToTokens for GeneratorField {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let name = &self.name;
        let member = &self.member;

        tokens.extend(quote!(
            .field(#name, &#member)
        ))
    }
}

pub struct GeneratorTimestamp {
    pub member: GeneratorMember,
}

impl ToTokens for GeneratorTimestamp {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let member = &self.member;

        tokens.extend(quote!(
            .timestamp(&#member)
        ))
    }
}

pub struct GeneratorImpl {
    pub target: String,
    pub measurement: GeneratorMeasurement,
    pub tags: Vec<GeneratorTag>,
    pub fields: Vec<GeneratorField>,
    pub timestamp: Option<GeneratorTimestamp>,
}

impl ToTokens for GeneratorImpl {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let target = format_ident!("{}", &self.target);
        let measurement = &self.measurement;
        let tags = &self.tags;
        let fields = &self.fields;

        let builder_tokens = if let Some(timestamp) = &self.timestamp {
            quote!(
                line_protocol::LineProtocolBuilder::default()
                    #measurement
                    #(#tags)*
                    #(#fields)*
                    #timestamp
                    .build()
            )
        } else {
            quote!(
                line_protocol::LineProtocolBuilder::default()
                    #measurement
                    #(#tags)*
                    #(#fields)*
                    .build()
            )
        };

        tokens.extend(quote!(
            impl LineProtocol for #target {
                fn to_line_protocol(&self) -> Option<String> {
                    #builder_tokens
                }
            }
        ));
    }
}

impl GeneratorImpl {
    pub fn tokenstream(&self) -> proc_macro2::TokenStream {
        quote!(#self)
    }
}