Skip to main content

serde_generate/
config.rs

1// Copyright (c) Facebook, Inc. and its affiliates
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use std::collections::{BTreeMap, BTreeSet, HashMap};
5
6/// Code generation options meant to be supported by all languages.
7#[derive(Clone, Debug)]
8pub struct CodeGeneratorConfig {
9    pub module_name: String,
10    pub serialization: bool,
11    pub encodings: BTreeSet<Encoding>,
12    pub external_definitions: ExternalDefinitions,
13    pub comments: DocComments,
14    pub custom_code: CustomCode,
15    pub enums: EnumConfig,
16    pub package_manifest: bool,
17}
18
19#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
20pub enum Encoding {
21    Bincode,
22    Bcs,
23}
24
25/// Track types definitions provided by external modules.
26pub type ExternalDefinitions =
27    std::collections::BTreeMap</* module */ String, /* type names */ Vec<String>>;
28
29/// Track documentation to be attached to particular definitions.
30pub type DocComments =
31    std::collections::BTreeMap</* qualified name */ Vec<String>, /* comment */ String>;
32
33/// Track custom code to be added to particular definitions (use with care!).
34pub type CustomCode = std::collections::BTreeMap<
35    /* qualified name */ Vec<String>,
36    /* custom code */ String,
37>;
38
39/// Configure the generation style of enums.
40#[derive(Clone, Debug)]
41pub struct EnumConfig {
42    // Generate [enum] if `true` or classes if `false`
43    pub c_style: bool,
44    // Generate sealed class if `true` or abstract class if `false`
45    pub sealed: bool,
46    // If `sealed` is true then the listed names will be abstract,
47    // if `sealed` is false then the listed names will be sealed.
48    pub output_type: HashMap<&'static str, &'static str>,
49}
50
51/// How to copy generated source code and available runtimes for a given language.
52pub trait SourceInstaller {
53    type Error;
54
55    /// Create a module exposing the container types contained in the registry.
56    fn install_module(
57        &self,
58        config: &CodeGeneratorConfig,
59        registry: &serde_reflection::Registry,
60    ) -> std::result::Result<(), Self::Error>;
61
62    /// Install the serde runtime.
63    fn install_serde_runtime(&self) -> std::result::Result<(), Self::Error>;
64
65    /// Install the bincode runtime.
66    fn install_bincode_runtime(&self) -> std::result::Result<(), Self::Error>;
67
68    /// Install the Libra Canonical Serialization (BCS) runtime.
69    fn install_bcs_runtime(&self) -> std::result::Result<(), Self::Error>;
70}
71
72impl CodeGeneratorConfig {
73    /// Default config for the given module name.
74    pub fn new(module_name: String) -> Self {
75        Self {
76            module_name,
77            serialization: true,
78            encodings: BTreeSet::new(),
79            external_definitions: BTreeMap::new(),
80            comments: BTreeMap::new(),
81            custom_code: BTreeMap::new(),
82            enums: EnumConfig {
83                c_style: false,
84                sealed: false,
85                output_type: HashMap::new(),
86            },
87            package_manifest: true,
88        }
89    }
90
91    pub fn module_name(&self) -> &str {
92        &self.module_name
93    }
94
95    /// Whether to include serialization methods.
96    pub fn with_serialization(mut self, serialization: bool) -> Self {
97        self.serialization = serialization;
98        self
99    }
100
101    /// Whether to include specialized methods for specific encodings.
102    pub fn with_encodings<I>(mut self, encodings: I) -> Self
103    where
104        I: IntoIterator<Item = Encoding>,
105    {
106        self.encodings = encodings.into_iter().collect();
107        self
108    }
109
110    /// Container names provided by external modules.
111    pub fn with_external_definitions(mut self, external_definitions: ExternalDefinitions) -> Self {
112        self.external_definitions = external_definitions;
113        self
114    }
115
116    /// Comments attached to particular entity.
117    pub fn with_comments(mut self, mut comments: DocComments) -> Self {
118        // Make sure comments end with a (single) newline.
119        for comment in comments.values_mut() {
120            *comment = format!("{}\n", comment.trim());
121        }
122        self.comments = comments;
123        self
124    }
125
126    /// Custom code attached to particular entity.
127    pub fn with_custom_code(mut self, code: CustomCode) -> Self {
128        self.custom_code = code;
129        self
130    }
131
132    /// Generate C-style enums (without variant data) as the target language
133    /// native enum type in supported languages.
134    pub fn with_c_style_enums(mut self, c_style_enums: bool) -> Self {
135        self.enums.c_style = c_style_enums;
136        self
137    }
138
139    /// For complex enums generate sealed enum classes instead of abstract classes
140    pub fn with_sealed_enums(mut self, sealed: bool) -> Self {
141        self.enums.sealed = sealed;
142        self
143    }
144
145    /// Generate abstract or sealed classes for data enums based on `with_sealed_enums`
146    /// but allow item by item overrides.
147    pub fn with_enum_type_overrides(
148        mut self,
149        overrides: HashMap<&'static str, &'static str>,
150    ) -> Self {
151        self.enums.output_type = overrides;
152        self
153    }
154
155    /// Generate a package manifest file for the target language.
156    pub fn with_package_manifest(mut self, package_manifest: bool) -> Self {
157        self.package_manifest = package_manifest;
158        self
159    }
160}
161
162impl Encoding {
163    pub fn name(self) -> &'static str {
164        match self {
165            Encoding::Bincode => "bincode",
166            Encoding::Bcs => "bcs",
167        }
168    }
169}