summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r--src/codegen/mod.rs134
1 files changed, 80 insertions, 54 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index f13bd65a..b8416314 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -2072,7 +2072,41 @@ impl MethodCodegen for Method {
}
}
-/// A helper type to construct enums, either bitfield ones or rust-style ones.
+/// A helper type that represents different enum variations.
+#[derive(Copy, Clone)]
+enum EnumVariation {
+ Rust,
+ Bitfield,
+ Consts,
+ ModuleConsts
+}
+
+impl EnumVariation {
+ fn is_rust(&self) -> bool {
+ match *self {
+ EnumVariation::Rust => true,
+ _ => false
+ }
+ }
+
+ fn is_bitfield(&self) -> bool {
+ match *self {
+ EnumVariation::Bitfield => true,
+ _ => false
+ }
+ }
+
+ /// Both the `Const` and `ModuleConsts` variants will cause this to return
+ /// true.
+ fn is_const(&self) -> bool {
+ match *self {
+ EnumVariation::Consts | EnumVariation::ModuleConsts => true,
+ _ => false
+ }
+ }
+}
+
+/// A helper type to construct different enum variations.
enum EnumBuilder<'a> {
Rust(quote::Tokens),
Bitfield {
@@ -2088,26 +2122,44 @@ enum EnumBuilder<'a> {
impl<'a> EnumBuilder<'a> {
/// Create a new enum given an item builder, a canonical name, a name for
- /// the representation, and whether it should be represented as a rust enum.
+ /// the representation, and which variation it should be generated as.
fn new(
name: &'a str,
attrs: Vec<quote::Tokens>,
repr: quote::Tokens,
- bitfield_like: bool,
- constify: bool,
- constify_module: bool,
+ enum_variation: EnumVariation
) -> Self {
let ident = quote::Ident::new(name);
- if bitfield_like {
- EnumBuilder::Bitfield {
- canonical_name: name,
- tokens: quote! {
+
+ match enum_variation {
+ EnumVariation::Bitfield => {
+ EnumBuilder::Bitfield {
+ canonical_name: name,
+ tokens: quote! {
+ #( #attrs )*
+ pub struct #ident (pub #repr);
+ },
+ }
+ }
+
+ EnumVariation::Rust => {
+ let mut tokens = quote! {
#( #attrs )*
- pub struct #ident (pub #repr);
- },
+ pub enum #ident
+ };
+ tokens.append("{");
+ EnumBuilder::Rust(tokens)
}
- } else if constify {
- if constify_module {
+
+ EnumVariation::Consts => {
+ EnumBuilder::Consts(vec![
+ quote! {
+ pub type #ident = #repr;
+ }
+ ])
+ }
+
+ EnumVariation::ModuleConsts => {
let ident = quote::Ident::new(CONSTIFIED_ENUM_MODULE_REPR_NAME);
let type_definition = quote! {
pub type #ident = #repr;
@@ -2117,20 +2169,7 @@ impl<'a> EnumBuilder<'a> {
module_name: name,
module_items: vec![type_definition],
}
- } else {
- EnumBuilder::Consts(vec![
- quote! {
- pub type #ident = #repr;
- }
- ])
}
- } else {
- let mut tokens = quote! {
- #( #attrs )*
- pub enum #ident
- };
- tokens.append("{");
- EnumBuilder::Rust(tokens)
}
}
@@ -2342,39 +2381,28 @@ impl CodeGenerator for Enum {
// FIXME(emilio): These should probably use the path so it can
// disambiguate between namespaces, just like is_opaque etc.
- let is_bitfield = {
- ctx.options().bitfield_enums.matches(&name) ||
- (enum_ty.name().is_none() &&
- self.variants().iter().any(|v| {
- ctx.options().bitfield_enums.matches(&v.name())
- }))
- };
-
- let is_constified_enum_module =
- self.is_constified_enum_module(ctx, item);
-
- let is_constified_enum = {
- is_constified_enum_module ||
- ctx.options().constified_enums.matches(&name) ||
- (enum_ty.name().is_none() &&
- self.variants().iter().any(|v| {
- ctx.options().constified_enums.matches(&v.name())
- }))
+ let variation = if self.is_bitfield(ctx, item) {
+ EnumVariation::Bitfield
+ } else if self.is_rustified_enum(ctx, item) {
+ EnumVariation::Rust
+ } else if self.is_constified_enum_module(ctx, item) {
+ EnumVariation::ModuleConsts
+ } else {
+ // We generate consts by default
+ EnumVariation::Consts
};
- let is_rust_enum = !is_bitfield && !is_constified_enum;
-
let mut attrs = vec![];
// FIXME: Rust forbids repr with empty enums. Remove this condition when
// this is allowed.
//
// TODO(emilio): Delegate this to the builders?
- if is_rust_enum {
+ if variation.is_rust() {
if !self.variants().is_empty() {
attrs.push(attributes::repr(repr_name));
}
- } else if is_bitfield {
+ } else if variation.is_bitfield() {
attrs.push(attributes::repr("C"));
}
@@ -2382,7 +2410,7 @@ impl CodeGenerator for Enum {
attrs.push(attributes::doc(comment));
}
- if !is_constified_enum {
+ if !variation.is_const() {
attrs.push(attributes::derives(
&["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"],
));
@@ -2427,9 +2455,7 @@ impl CodeGenerator for Enum {
&name,
attrs,
repr,
- is_bitfield,
- is_constified_enum,
- is_constified_enum_module,
+ variation
);
// A map where we keep a value -> variant relation.
@@ -2475,7 +2501,7 @@ impl CodeGenerator for Enum {
match seen_values.entry(variant.val()) {
Entry::Occupied(ref entry) => {
- if is_rust_enum {
+ if variation.is_rust() {
let variant_name = ctx.rust_mangle(variant.name());
let mangled_name =
if is_toplevel || enum_ty.name().is_some() {
@@ -2523,7 +2549,7 @@ impl CodeGenerator for Enum {
// If it's an unnamed enum, or constification is enforced,
// we also generate a constant so it can be properly
// accessed.
- if (is_rust_enum && enum_ty.name().is_none()) ||
+ if (variation.is_rust() && enum_ty.name().is_none()) ||
variant.force_constification()
{
let mangled_name = if is_toplevel {