diff --git a/serde-generate/src/config.rs b/serde-generate/src/config.rs
index c964bb9de..a206bd668 100644
--- a/serde-generate/src/config.rs
+++ b/serde-generate/src/config.rs
@@ -1,7 +1,7 @@
// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0
-use std::collections::{BTreeMap, BTreeSet};
+use std::collections::{BTreeMap, BTreeSet, HashMap};
/// Code generation options meant to be supported by all languages.
#[derive(Clone, Debug)]
@@ -12,7 +12,7 @@ pub struct CodeGeneratorConfig {
pub external_definitions: ExternalDefinitions,
pub comments: DocComments,
pub custom_code: CustomCode,
- pub c_style_enums: bool,
+ pub enums: EnumConfig,
pub package_manifest: bool,
}
@@ -36,6 +36,18 @@ pub type CustomCode = std::collections::BTreeMap<
/* custom code */ String,
>;
+/// Configure the generation style of enums.
+#[derive(Clone, Debug)]
+pub struct EnumConfig {
+ // Generate [enum] if `true` or classes if `false`
+ pub c_style: bool,
+ // Generate sealed class if `true` or abstract class if `false`
+ pub sealed: bool,
+ // If `sealed_enums` is true then the listed names will be abstract,
+ // if `sealed_enums` is false then the listed names will be sealed.
+ pub output_type: HashMap<&'static str, &'static str>,
+}
+
/// How to copy generated source code and available runtimes for a given language.
pub trait SourceInstaller {
type Error;
@@ -67,7 +79,11 @@ impl CodeGeneratorConfig {
external_definitions: BTreeMap::new(),
comments: BTreeMap::new(),
custom_code: BTreeMap::new(),
- c_style_enums: false,
+ enums: EnumConfig {
+ c_style: false,
+ sealed: false,
+ output_type: HashMap::new(),
+ },
package_manifest: true,
}
}
@@ -116,7 +132,23 @@ impl CodeGeneratorConfig {
/// Generate C-style enums (without variant data) as the target language
/// native enum type in supported languages.
pub fn with_c_style_enums(mut self, c_style_enums: bool) -> Self {
- self.c_style_enums = c_style_enums;
+ self.enums.c_style = c_style_enums;
+ self
+ }
+
+ /// For complex enums generate sealed enum classes instead of abstract classes
+ pub fn with_sealed_enums(mut self, sealed: bool) -> Self {
+ self.enums.sealed = sealed;
+ self
+ }
+
+ /// Generate abstract or sealed classes for data enums based on `with_sealed_enums`
+ /// but allow item by item overrides.
+ pub fn with_enum_type_overrides(
+ mut self,
+ overrides: HashMap<&'static str, &'static str>,
+ ) -> Self {
+ self.enums.output_type = overrides;
self
}
diff --git a/serde-generate/src/cpp.rs b/serde-generate/src/cpp.rs
index 3bd0582ba..48763d89d 100644
--- a/serde-generate/src/cpp.rs
+++ b/serde-generate/src/cpp.rs
@@ -40,7 +40,7 @@ struct CppEmitter<'a, T> {
impl<'a> CodeGenerator<'a> {
/// Create a C++ code generator for the given config.
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("C++ does not support generating c-style enums");
}
let mut external_qualified_names = HashMap::new();
diff --git a/serde-generate/src/csharp.rs b/serde-generate/src/csharp.rs
index ccde48d42..026cb192b 100644
--- a/serde-generate/src/csharp.rs
+++ b/serde-generate/src/csharp.rs
@@ -83,7 +83,7 @@ impl<'a> CodeGenerator<'a> {
// When we find an enum with all Unit variants, we ser/de as a regular C# enum.
// We keep track of this so we can use the enum's extension class for ser/de since enums can't have methods.
let mut cstyle_enum_names = Vec::new();
- if self.config.c_style_enums {
+ if self.config.enums.c_style {
for (name, format) in registry {
if let ContainerFormat::Enum(variants) = format {
if variants.values().all(|f| f.value == VariantFormat::Unit) {
@@ -1214,7 +1214,7 @@ impl crate::SourceInstaller for Installer {
-{}
+{}
"#,
diff --git a/serde-generate/src/dart.rs b/serde-generate/src/dart.rs
index bff5e80cd..6db29d456 100644
--- a/serde-generate/src/dart.rs
+++ b/serde-generate/src/dart.rs
@@ -192,7 +192,7 @@ where
// in Dart enums cannot have a static method added to them
// yet so we must call the extension class instead
fn get_class(&self, name: &str) -> String {
- if self.generator.config.c_style_enums {
+ if self.generator.config.enums.c_style {
use ContainerFormat::Enum;
match self.get_field_container_type(name) {
// if we have an enum AND all of that enum's members are Unit
@@ -583,12 +583,19 @@ return obj;
Struct(fields) => fields.clone(),
Enum(variants) => {
// When we find an enum with all Unit variants, we ser/de as a regular Dart enum.
- if self.generator.config.c_style_enums
+ if ((self.generator.config.enums.c_style
+ && !self.generator.config.enums.output_type.contains_key(name))
+ || self.generator.config.enums.output_type.get(name) == Some(&"enum"))
&& variants.values().all(|f| f.value == VariantFormat::Unit)
{
self.output_enum_container(name, variants)?;
+ } else if (self.generator.config.enums.sealed
+ && !self.generator.config.enums.output_type.contains_key(name))
+ || self.generator.config.enums.output_type.get(name) == Some(&"sealed")
+ {
+ self.output_enum_class_container(name, variants, "sealed")?;
} else {
- self.output_enum_class_container(name, variants)?;
+ self.output_enum_class_container(name, variants, "abstract")?;
}
return Ok(());
}
@@ -1052,12 +1059,14 @@ switch (this) {{"#,
&mut self,
name: &str,
variants: &BTreeMap>,
+ class_type: &str,
) -> Result<()> {
writeln!(self.out)?;
self.output_comment(name)?;
writeln!(
self.out,
- "abstract class {} {{",
+ "{} class {} {{",
+ class_type,
self.quote_qualified_name(name)
)?;
self.enter_class(name);
diff --git a/serde-generate/src/golang.rs b/serde-generate/src/golang.rs
index 1a9128b16..aad179f4a 100644
--- a/serde-generate/src/golang.rs
+++ b/serde-generate/src/golang.rs
@@ -39,7 +39,7 @@ struct GoEmitter<'a, T> {
impl<'a> CodeGenerator<'a> {
/// Create a Go code generator for the given config.
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("Go does not support generating c-style enums");
}
let mut external_qualified_names = HashMap::new();
diff --git a/serde-generate/src/java.rs b/serde-generate/src/java.rs
index f800812be..b885c9b77 100644
--- a/serde-generate/src/java.rs
+++ b/serde-generate/src/java.rs
@@ -42,7 +42,7 @@ struct JavaEmitter<'a, T> {
impl<'a> CodeGenerator<'a> {
/// Create a Java code generator for the given config.
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("Java does not support generating c-style enums");
}
let mut external_qualified_names = HashMap::new();
diff --git a/serde-generate/src/ocaml.rs b/serde-generate/src/ocaml.rs
index f3a2a2f4c..5f44c4eb7 100644
--- a/serde-generate/src/ocaml.rs
+++ b/serde-generate/src/ocaml.rs
@@ -30,7 +30,7 @@ struct OCamlEmitter<'a, T> {
impl<'a> CodeGenerator<'a> {
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("OCaml does not support generating c-style enums");
}
Self {
diff --git a/serde-generate/src/python3.rs b/serde-generate/src/python3.rs
index af5eaf81b..abb054d30 100644
--- a/serde-generate/src/python3.rs
+++ b/serde-generate/src/python3.rs
@@ -37,7 +37,7 @@ struct PythonEmitter<'a, T> {
impl<'a> CodeGenerator<'a> {
/// Create a Python code generator for the given config.
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("Python 3 does not support generating c-style enums");
}
let mut external_qualified_names = HashMap::new();
diff --git a/serde-generate/src/solidity.rs b/serde-generate/src/solidity.rs
index 4d18c07e3..0bbd45f5a 100644
--- a/serde-generate/src/solidity.rs
+++ b/serde-generate/src/solidity.rs
@@ -1455,7 +1455,7 @@ impl SolRegistry {
impl<'a> CodeGenerator<'a> {
/// Create a solidity code generator for the given config.
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("Solidity does not support generating c-style enums");
}
Self { config }
diff --git a/serde-generate/src/swift.rs b/serde-generate/src/swift.rs
index b80fb8154..1035e4640 100644
--- a/serde-generate/src/swift.rs
+++ b/serde-generate/src/swift.rs
@@ -39,7 +39,7 @@ struct SwiftEmitter<'a, T> {
impl<'a> CodeGenerator<'a> {
/// Create a Swift code generator for the given config.
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("Swift does not support generating c-style enums");
}
let mut external_qualified_names = HashMap::new();
diff --git a/serde-generate/src/typescript.rs b/serde-generate/src/typescript.rs
index be8889d61..efeee7922 100644
--- a/serde-generate/src/typescript.rs
+++ b/serde-generate/src/typescript.rs
@@ -38,7 +38,7 @@ struct TypeScriptEmitter<'a, T> {
impl<'a> CodeGenerator<'a> {
/// Create a TypeScript code generator for the given config.
pub fn new(config: &'a CodeGeneratorConfig) -> Self {
- if config.c_style_enums {
+ if config.enums.c_style {
panic!("TypeScript does not support generating c-style enums");
}
let mut external_qualified_names = HashMap::new();