codgenhelp 0.0.1

Simplifies structure and enum parsing in Macros1.1
Documentation


use super::{Fields};
use super::super::{Lit,FromLiteral};
use super::super::syn::{VariantData,ConstExpr,Variant as SynVariant, Body};
macro_rules! is_thing {
    ($name:ident, $ma: pat) => {
        #[inline(always)]
        #[allow(dead_code)]
        pub fn $name(&self) -> bool {
            match self {
                $ma => true,
                _ => false
            }
        }
    }
}



/// There are multiple _types_ of structures in Rust.
#[derive(Clone,Debug)]
pub enum Structure {
    /// The normal structure which has several fields
    ///
    /// Example: `pub struct AStruct{ a: u64, b: u64 }`
    NormalStruct(Fields),
    /// A tuple struct which is just a named tuple
    ///
    /// Example: `pub struct AStruct( u64, u64);`
    TupleStruct(Fields),
    /// A structure that contains no data
    ///
    /// Example: `pub struct ZeroSizedStruct;`
    Unit,
    /// Literal Value
    ///
    /// A structure cannot actually be this type. But Enum's as they can be declared with a
    /// constant value.
    Discriminant(Lit)
}
impl Structure {
    /// Build a structure from `syn`'s representation
    pub fn from_syn_variant(x: &SynVariant) -> Result<Structure,String> {
        match &x.discriminant {
            &Option::None => { },
            &Option::Some(ConstExpr::Lit(ref x)) => return Ok(Structure::Discriminant(x.clone())),
            &Option::Some(_) => return Err("Encountered `Variant` who's discriminant existed BUT that value wasn't a literal".to_string())
        };
        Ok(Structure::from_variantdata(&x.data))
    }
    /// Build a structure from `syn`'s representation
    #[inline(always)]
    pub fn from_variantdata(x: &VariantData) -> Structure {
        match x {
            &VariantData::Unit => Structure::Unit,
            &VariantData::Tuple(ref f) => Structure::TupleStruct(Fields::from(f)),
            &VariantData::Struct(ref f) => Structure::NormalStruct(Fields::from(f))
        }
    }

    /// Build from `syn`'s Body representation
    pub fn from_body(x: &Body) -> Result<Structure,String> {
        match x {
            &Body::Enum(_) => Err("Attempted to parse struct but encountered a enum".to_string()),
            &Body::Struct(ref x) => Ok(Structure::from_variantdata(x))
        }
    }
    is_thing!(is_unit,&Structure::Unit);
    is_thing!(is_norm,&Structure::NormalStruct(_));
    is_thing!(is_tuple,&Structure::TupleStruct(_));
    is_thing!(is_discriminant,&Structure::Discriminant(_));
    /// Get Fields
    ///
    /// Returns Fields if this Struct is a Tuple or Normal
    pub fn get_fields<'a>(&'a self) -> Option<&'a Fields> {
        match self {
            &Structure::NormalStruct(ref f) |
            &Structure::TupleStruct(ref f) => Some(f),
            _ => None
        }
    }

    /// Get Literal
    ///
    /// Returns the literal value if this is a Discrimninat structure
    pub fn get_literal<'a>(&'a self) -> Option<&'a Lit> {
        match self {
            &Structure::Discriminant(ref l) => Some(l),
            _ => None
        }
    }

    /// Get From Literal
    ///
    /// Pre-Perform the conversion
    pub fn from_literal(&self) -> Option<FromLiteral> {
        match self.get_literal() {
            Option::Some(x) => Some(FromLiteral::from(x)),
            _ => None
        }
    }
}