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}