arma-rs-proc 1.13.0

proc macros for arma-rs
Documentation
use proc_macro2::{Span, TokenStream};
use quote::ToTokens;
use syn::{Error, Result};

use crate::derive::{
    CombinedErrors,
    attributes::{ContainerAttributes, FieldAttributes, parse_attributes},
    r#struct,
};

pub struct ContainerData {
    pub attributes: ContainerAttributes,
    pub ident: syn::Ident,
    pub generics: syn::Generics,
    pub data: Data,
}

pub enum Data {
    Struct(StructData),
}

pub enum StructData {
    Map(Vec<FieldNamed>),
    Tuple(Vec<FieldUnnamed>),
    NewType(Box<FieldUnnamed>),
}

impl ContainerData {
    pub fn from_input(errors: &mut CombinedErrors, input: syn::DeriveInput) -> Result<Self> {
        let data = match input.data {
            syn::Data::Struct(data) => Data::Struct(StructData::new(errors, data)?),
            syn::Data::Enum(_) => Err(Error::new(Span::call_site(), "enums aren't supported"))?,
            syn::Data::Union(_) => Err(Error::new(Span::call_site(), "unions aren't supported"))?,
        };
        let attributes = parse_attributes::<ContainerAttributes>(errors, &input.attrs);

        Ok(Self {
            attributes,
            ident: input.ident,
            generics: input.generics,
            data,
        })
    }

    pub fn validate_attributes(&self, errors: &mut CombinedErrors) {
        match self.data {
            Data::Struct(ref data) => {
                r#struct::validate_attributes(errors, &self.attributes, data);
            }
        }
    }

    pub fn impl_into_arma(&self) -> TokenStream {
        match self.data {
            Data::Struct(ref data) => r#struct::impl_into_arma(&self.attributes, data),
        }
    }

    pub fn impl_from_arma(&self) -> TokenStream {
        match self.data {
            Data::Struct(ref data) => r#struct::impl_from_arma(&self.attributes, data),
        }
    }
}

pub struct FieldNamed {
    pub attributes: FieldAttributes,
    pub ident: syn::Ident,
    pub name: String,
    pub _ty: syn::Type,
}

pub struct FieldUnnamed {
    pub attributes: FieldAttributes,
    pub index: syn::Index,
    pub ty: syn::Type,
}

impl FieldNamed {
    pub fn new(errors: &mut CombinedErrors, field: syn::Field) -> Self {
        let ident = field.ident.unwrap();
        let name = ident.to_string();
        Self {
            attributes: parse_attributes::<FieldAttributes>(errors, &field.attrs),
            ident,
            name,
            _ty: field.ty,
        }
    }
}

impl FieldUnnamed {
    pub fn new(errors: &mut CombinedErrors, field: syn::Field, index: usize) -> Self {
        Self {
            attributes: parse_attributes::<FieldAttributes>(errors, &field.attrs),
            index: syn::Index::from(index),
            ty: field.ty,
        }
    }
}

pub trait Field {
    fn attributes(&self) -> &FieldAttributes;
    fn token(&self) -> TokenStream;
}

impl Field for FieldNamed {
    fn attributes(&self) -> &FieldAttributes {
        &self.attributes
    }

    fn token(&self) -> TokenStream {
        self.ident.to_token_stream()
    }
}

impl Field for FieldUnnamed {
    fn attributes(&self) -> &FieldAttributes {
        &self.attributes
    }

    fn token(&self) -> TokenStream {
        self.index.to_token_stream()
    }
}