diff --git a/syntax/attrs.rs b/syntax/attrs.rs index f48a210e..16541a3f 100644 --- a/syntax/attrs.rs +++ b/syntax/attrs.rs @@ -1,5 +1,7 @@ use crate::syntax::report::Errors; +use crate::syntax::Atom::{self, *}; use crate::syntax::{Derive, Doc}; +use proc_macro2::Ident; use syn::parse::{ParseStream, Parser as _}; use syn::{Attribute, Error, LitStr, Path, Result, Token}; @@ -7,6 +9,7 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token}; pub struct Parser<'a> { pub doc: Option<&'a mut Doc>, pub derives: Option<&'a mut Vec>, + pub repr: Option<&'a mut Option>, } pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc { @@ -44,6 +47,16 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) { } Err(err) => return cx.push(err), } + } else if attr.path.is_ident("repr") { + match attr.parse_args_with(parse_repr_attribute) { + Ok(attr) => { + if let Some(repr) = &mut parser.repr { + **repr = Some(attr); + continue; + } + } + Err(err) => return cx.push(err), + } } return cx.error(attr, "unsupported attribute"); } @@ -69,3 +82,18 @@ fn parse_derive_attribute(input: ParseStream) -> Result> { }) .collect() } + +fn parse_repr_attribute(input: ParseStream) -> Result { + let begin = input.cursor(); + let ident: Ident = input.parse()?; + if let Some(atom) = Atom::from(&ident) { + match atom { + U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize => return Ok(atom), + _ => {} + } + } + Err(Error::new_spanned( + begin.token_stream(), + "unrecognized repr", + )) +} diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs index 388a117a..c65b3f4b 100644 --- a/syntax/discriminant.rs +++ b/syntax/discriminant.rs @@ -20,9 +20,9 @@ pub struct Discriminant { } impl DiscriminantSet { - pub fn new() -> Self { + pub fn new(repr: Option) -> Self { DiscriminantSet { - repr: None, + repr, values: BTreeSet::new(), previous: None, } diff --git a/syntax/parse.rs b/syntax/parse.rs index ab5dcc14..a11a5c88 100644 --- a/syntax/parse.rs +++ b/syntax/parse.rs @@ -60,6 +60,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result { attrs::Parser { doc: Some(&mut doc), derives: Some(&mut derives), + ..Default::default() }, ); @@ -103,10 +104,20 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result { )); } - let doc = attrs::parse_doc(cx, &item.attrs); + let mut doc = Doc::new(); + let mut repr = None; + attrs::parse( + cx, + &item.attrs, + attrs::Parser { + doc: Some(&mut doc), + repr: Some(&mut repr), + ..Default::default() + }, + ); let mut variants = Vec::new(); - let mut discriminants = DiscriminantSet::new(); + let mut discriminants = DiscriminantSet::new(repr); for variant in item.variants { match variant.fields { Fields::Unit => {}