tighterror_build/coder/
options.rs

1use crate::errors::TbError;
2use std::path::PathBuf;
3
4/// Options for the code generator.
5///
6/// This struct is a builder for the code generator options.
7///
8/// # Examples
9/// ```no_run
10/// # use tighterror_build::{CodegenOptions, errors::TbError};
11/// # pub fn foo() -> Result<(), TbError> {
12/// CodegenOptions::new()
13///     .spec("tighterror.yaml".to_owned())
14///     .output("src/errors.rs".to_owned())
15///     .codegen()?;
16/// # Ok(())
17/// # }
18/// # foo().unwrap();
19/// ```
20#[derive(Debug, Clone, Default)]
21pub struct CodegenOptions {
22    pub(crate) spec: Option<PathBuf>,
23    pub(crate) output: Option<PathBuf>,
24    pub(crate) test: Option<bool>,
25    pub(crate) update: Option<bool>,
26    pub(crate) separate_files: Option<bool>,
27}
28
29impl CodegenOptions {
30    /// Creates a new options object with default values.
31    pub fn new() -> Self {
32        Self::default()
33    }
34
35    /// Sets the specification file path.
36    ///
37    /// If a value is not specified the default specification filenames
38    /// are used in the following order:
39    /// * if the `yaml` feature is enabled the path [DEFAULT_SPEC_PATH_YAML]
40    ///   is used
41    /// * if specification file is still not found and the `toml` feature is
42    ///   enabled the path [DEFAULT_SPEC_PATH_TOML] is used
43    ///
44    /// # Examples
45    /// ```rust
46    /// # use tighterror_build::CodegenOptions;
47    /// CodegenOptions::new().spec("tighterror.yaml");
48    /// ```
49    ///
50    /// [DEFAULT_SPEC_PATH_YAML]: crate::DEFAULT_SPEC_PATH_YAML
51    /// [DEFAULT_SPEC_PATH_TOML]: crate::DEFAULT_SPEC_PATH_TOML
52    pub fn spec(&mut self, spec: impl Into<PathBuf>) -> &mut Self {
53        self.spec = Some(spec.into());
54        self
55    }
56
57    /// Sets the specification file path option.
58    ///
59    /// This method enhances [`spec`](Self::spec) to set the specification
60    /// file path option. This is handy when one needs to
61    /// reset the option back to `None` or has an `Option<PathBuf>` parsed
62    /// from command line.
63    ///
64    /// # Examples
65    /// ```rust
66    /// # use tighterror_build::CodegenOptions;
67    /// CodegenOptions::new().spec_option(None);
68    /// CodegenOptions::new().spec_option(Some("tighterror.yaml".into()));
69    /// ```
70    pub fn spec_option(&mut self, spec: Option<PathBuf>) -> &mut Self {
71        self.spec = spec;
72        self
73    }
74
75    /// Sets the output path.
76    ///
77    /// This can be either an absolute path, a relative path, or hyphen `-`.
78    /// A relative path is relative to the location of the specification file.
79    ///
80    /// If the path points to an existing directory the behavior depends on
81    /// *separate files* mode. If *separate files* is disabled the output is
82    /// written into file `tighterror.rs` under the directory.
83    /// See [`separate_files`](Self::separate_files) for the case when the mode
84    /// is enabled.
85    ///
86    /// If the value is a hyphen `-`, or output path is not set at all, the
87    /// output is written to `stdout`.
88    ///
89    /// A `Some` value defined here overrides the `MainObject::output` attribute
90    /// in the specification file.
91    ///
92    /// # Examples
93    ///
94    /// ```rust
95    /// # use tighterror_build::CodegenOptions;
96    /// CodegenOptions::new().output("src/errors.rs");
97    /// ```
98    pub fn output(&mut self, output: impl Into<PathBuf>) -> &mut Self {
99        self.output = Some(output.into());
100        self
101    }
102
103    /// Sets the output path option.
104    ///
105    /// This method enhances [`output`](Self::output) to set the output path
106    /// option. This is handy when one needs to reset the option back to `None`
107    /// or has an `Option<PathBuf>` parsed from command line.
108    ///
109    /// # Examples
110    /// ```rust
111    ///  # use tighterror_build::CodegenOptions;
112    /// CodegenOptions::new().output_option(None);
113    /// CodegenOptions::new().output_option(Some("./src".into()));
114    /// ```
115    pub fn output_option(&mut self, output: Option<PathBuf>) -> &mut Self {
116        self.output = output;
117        self
118    }
119
120    /// Enables the unit test.
121    ///
122    /// When enabled a module unit-test is included in the generated code.
123    ///
124    /// In `no_std` environments test cases that require `std` are excluded.
125    ///
126    /// # Examples
127    /// ```rust
128    /// # use tighterror_build::CodegenOptions;
129    /// CodegenOptions::new().test(None);
130    /// CodegenOptions::new().test(true);
131    /// CodegenOptions::new().test(Some(false));
132    /// ```
133    pub fn test(&mut self, test: impl Into<Option<bool>>) -> &mut Self {
134        self.test = test.into();
135        self
136    }
137
138    /// Enables the *update* mode.
139    ///
140    /// If the value is `true` and the output file already exists
141    /// it is not overwritten if the new content equals the existing one.
142    ///
143    /// This option is useful to avoid recompilation of a crate, because
144    /// `cargo` rebuilds a crate when one of the source file's modification
145    /// time changes. When using the *update* mode the modification time
146    /// changes only when the file data changes, and recompilation is really
147    /// needed. Without *update* mode the output file is overwritten
148    /// unconditionally, even when the new data equals the existing one.
149    /// This may cause an unnecessary recompilation.
150    ///
151    /// # Examples
152    /// ```rust
153    /// # use tighterror_build::CodegenOptions;
154    /// CodegenOptions::new().update(None);
155    /// CodegenOptions::new().update(true);
156    /// CodegenOptions::new().update(Some(false));
157    /// ```
158    pub fn update(&mut self, update: impl Into<Option<bool>>) -> &mut Self {
159        self.update = update.into();
160        self
161    }
162
163    /// Enables the *separate files* mode.
164    ///
165    /// When enabled every module in specification is written to a separate
166    /// file. The [`output`](Self::output) option must point to an
167    /// existing directory. The module files, named after the modules
168    /// with addition of the `.rs` suffix, are written under the directory.
169    ///
170    /// For example, assuming `output` equals `./src` and there
171    /// are two modules named `errors` and `internal_errors`, the modules will
172    /// be written to `./src/errors.rs` and `./src/internal_errors.rs`
173    /// respectively.
174    ///
175    /// If the output is written to `stdout` the *separate files* mode is
176    /// implicitly disabled.
177    pub fn separate_files(&mut self, separate_files: impl Into<Option<bool>>) -> &mut Self {
178        self.separate_files = separate_files.into();
179        self
180    }
181
182    /// Invokes the code generator [main function] using these options.
183    ///
184    /// See the struct documentation for a full example.
185    ///
186    /// [main function]: crate::codegen
187    pub fn codegen(&self) -> Result<(), TbError> {
188        super::codegen(self)
189    }
190}