Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions serde-generate/src/config.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -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,
}

Expand All @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean "If sealed is true" etc?

// 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;
Expand Down Expand Up @@ -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,
}
}
Expand Down Expand Up @@ -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`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typo: extra space "enums based"

/// 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
}

Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions serde-generate/src/csharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -1214,7 +1214,7 @@ impl crate::SourceInstaller for Installer {
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
{}
{}
</ItemGroup>
</Project>
"#,
Expand Down
17 changes: 13 additions & 4 deletions serde-generate/src/dart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we're not using output_type as much when the value is not "enum" or "sealed", right?

{
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(());
}
Expand Down Expand Up @@ -1052,12 +1059,14 @@ switch (this) {{"#,
&mut self,
name: &str,
variants: &BTreeMap<u32, Named<VariantFormat>>,
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);
Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/golang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/java.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/ocaml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/python3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/solidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/swift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion serde-generate/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading