edres_core/options.rs
1//! This module contains the structs for configuring the behaviour of the public APIs.
2//!
3//! The main struct of this module is `Options` which contains
4//! all of the different configuration options.
5//!
6//! Most structs have a `new` constructor which contains sensible
7//! defaults, as well as a `minimal` constructor which generates
8//! as little code as possible.
9
10use std::borrow::Cow;
11
12/// Contains the full set of options for all public APIs
13/// in this crate.
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct Options {
16 /// In present, generates a const with this name that
17 /// stores the path of the original markup file.
18 pub source_path_const_name: Option<Cow<'static, str>>,
19
20 /// Controls whether generated items should derive `serde` traits.
21 pub serde_support: SerdeSupport,
22
23 /// See [`ParseOptions`].
24 pub parse: ParseOptions,
25
26 /// See [`StructOptions`].
27 pub structs: StructOptions,
28
29 /// See [`EnumOptions`].
30 pub enums: EnumOptions,
31
32 /// See [`FilesOptions`].
33 pub files: FilesOptions,
34
35 /// See [`OutputOptions`].
36 pub output: OutputOptions,
37}
38
39impl Options {
40 /// # Examples
41 /// ```
42 /// # use edres_core::options::*;
43 /// assert_eq!(Options::new(), Options {
44 /// source_path_const_name: Some("SOURCE_PATH".into()),
45 /// serde_support: SerdeSupport::No,
46 /// parse: ParseOptions::new(),
47 /// structs: StructOptions::new(),
48 /// enums: EnumOptions::new(),
49 /// files: FilesOptions::new(),
50 /// output: OutputOptions::new(),
51 /// });
52 /// ```
53 pub const fn new() -> Options {
54 Options {
55 source_path_const_name: Some(Cow::Borrowed("SOURCE_PATH")),
56 serde_support: SerdeSupport::No,
57
58 parse: ParseOptions::new(),
59 structs: StructOptions::new(),
60 enums: EnumOptions::new(),
61 files: FilesOptions::new(),
62 output: OutputOptions::new(),
63 }
64 }
65
66 /// # Examples
67 /// ```
68 /// # use edres_core::options::*;
69 /// assert_eq!(Options::serde_default(), Options {
70 /// source_path_const_name: Some("SOURCE_PATH".into()),
71 /// serde_support: SerdeSupport::Yes,
72 /// parse: ParseOptions::new(),
73 /// structs: StructOptions::new(),
74 /// enums: EnumOptions::new(),
75 /// files: FilesOptions::new(),
76 /// output: OutputOptions::new(),
77 /// });
78 /// ```
79 pub const fn serde_default() -> Options {
80 Options {
81 source_path_const_name: Some(Cow::Borrowed("SOURCE_PATH")),
82 serde_support: SerdeSupport::Yes,
83
84 parse: ParseOptions::new(),
85 structs: StructOptions::new(),
86 enums: EnumOptions::new(),
87 files: FilesOptions::new(),
88 output: OutputOptions::new(),
89 }
90 }
91
92 /// ```
93 /// # use edres_core::options::*;
94 /// assert_eq!(Options::minimal(), Options {
95 /// source_path_const_name: None,
96 /// serde_support: SerdeSupport::No,
97 /// parse: ParseOptions::new(),
98 /// structs: StructOptions::minimal(),
99 /// enums: EnumOptions::minimal(),
100 /// files: FilesOptions::minimal(),
101 /// output: OutputOptions::new(),
102 /// });
103 /// ```
104 pub const fn minimal() -> Options {
105 Options {
106 source_path_const_name: None,
107 serde_support: SerdeSupport::No,
108
109 parse: ParseOptions::new(),
110 structs: StructOptions::minimal(),
111 enums: EnumOptions::minimal(),
112 files: FilesOptions::minimal(),
113 output: OutputOptions::new(),
114 }
115 }
116}
117
118impl Default for Options {
119 /// # Examples
120 /// ```
121 /// # use edres_core::options::*;
122 /// assert_eq!(Options::default(), Options::new());
123 /// ```
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129/// Options specific to how `edres` should parse markup.
130#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct ParseOptions {
132 /// The floating point type to infer from input.
133 ///
134 /// This can be either `f32` or `f64`. Values that are too
135 /// large to fit the chosen default will instead be inferred
136 /// as a larger type.
137 pub default_float_size: FloatSize,
138
139 /// The integer type to infer from input.
140 ///
141 /// This can be anything from `i8` to `i128`, including
142 /// `isize`. Values that are too large to fit the chosen
143 /// default will instead be inferred as a larger type.
144 pub default_int_size: IntSize,
145
146 /// What size of sequence, if any, to consider small enough
147 /// to use an array instead of a `Vec`.
148 ///
149 /// For example, if `Some(4)` is provided, then sequences of
150 /// more than 4 items in the input will generate a `Vec` in
151 /// the resulting struct. Meanwhile, a sequence of 4 values
152 /// would instead generate a `[T; 4]`.
153 pub max_array_size: Option<usize>,
154}
155
156impl ParseOptions {
157 /// # Examples
158 /// ```
159 /// # use edres_core::options::*;
160 /// assert_eq!(ParseOptions::new(), ParseOptions {
161 /// default_float_size: FloatSize::F64,
162 /// default_int_size: IntSize::I64,
163 /// max_array_size: None,
164 /// });
165 /// ```
166 pub const fn new() -> Self {
167 ParseOptions {
168 default_float_size: FloatSize::F64,
169 default_int_size: IntSize::I64,
170 max_array_size: None,
171 }
172 }
173}
174
175impl Default for ParseOptions {
176 /// # Examples
177 /// ```
178 /// # use edres_core::options::*;
179 /// assert_eq!(ParseOptions::default(), ParseOptions::new());
180 /// ```
181 fn default() -> Self {
182 ParseOptions::new()
183 }
184}
185
186/// Options specific to how `edres` should generate structs.
187#[derive(Debug, Clone, PartialEq, Eq)]
188pub struct StructOptions {
189 /// A list of traits to derive.
190 ///
191 /// These can either be unqualified (like `Clone`) or
192 /// qualifier with a crate name (like `serde::Serialize`).
193 ///
194 /// See the `StructOptions::new` example to see how to easily
195 /// set this value.
196 pub derived_traits: Cow<'static, [Cow<'static, str>]>,
197
198 /// If present, generates a const with the given name that
199 /// stores the contents of the file as a value of the generated
200 /// type.
201 pub struct_data_const_name: Option<Cow<'static, str>>,
202}
203
204impl StructOptions {
205 /// # Examples
206 /// ```
207 /// # use edres_core::options::*;
208 /// assert_eq!(StructOptions::new(), StructOptions {
209 /// derived_traits: vec!["Debug".into()].into(),
210 /// struct_data_const_name: Some("DATA".into()),
211 /// });
212 /// ```
213 pub const fn new() -> StructOptions {
214 StructOptions {
215 derived_traits: Cow::Borrowed(&[Cow::Borrowed("Debug")]),
216 struct_data_const_name: Some(Cow::Borrowed("DATA")),
217 }
218 }
219
220 /// # Examples
221 /// ```
222 /// # use edres_core::options::*;
223 /// assert_eq!(StructOptions::minimal(), StructOptions {
224 /// derived_traits: vec![].into(),
225 /// struct_data_const_name: None,
226 /// });
227 /// ```
228 pub const fn minimal() -> StructOptions {
229 StructOptions {
230 derived_traits: Cow::Borrowed(&[]),
231 struct_data_const_name: None,
232 }
233 }
234}
235
236impl Default for StructOptions {
237 /// # Examples
238 /// ```
239 /// # use edres_core::options::*;
240 /// assert_eq!(StructOptions::default(), StructOptions::new());
241 /// ```
242 fn default() -> Self {
243 Self::new()
244 }
245}
246
247/// Options specific to how `edres` should generate enums.
248#[derive(Debug, Clone, PartialEq, Eq)]
249pub struct EnumOptions {
250 /// A list of traits to derive.
251 ///
252 /// These can either be unqualified (like `Clone`) or
253 /// qualifier with a crate name (like `serde::Serialize`).
254 ///
255 /// See the `EnumOptions::new` example to see how to easily
256 /// set this value.
257 pub derived_traits: Cow<'static, [Cow<'static, str>]>,
258
259 /// Whether generated enums should implement the `Default`
260 /// trait.
261 ///
262 /// This uses the first variant as the default value.
263 pub impl_default: bool,
264
265 /// Whether generated enums should implement `Display`.
266 ///
267 /// This just displays the name of the variant as a string.
268 /// For example, `MyEnum::First.to_string() == "First"`.
269 pub impl_display: bool,
270
271 /// Whether generated enums should implement `FromStr`.
272 ///
273 /// This works by matching the name of the variant.
274 /// For example, `"First".parse().unwrap() == MyEnum::First`.
275 pub impl_from_str: bool,
276
277 /// If present, generates a const with this name that stores
278 /// a slice of all variants of the generated enum.
279 pub all_variants_const_name: Option<Cow<'static, str>>,
280
281 /// If present, generates a const with this name that stores
282 /// a slice of all values corresponding to the enum variants.
283 ///
284 /// This requires `values_struct` to be set as well.
285 pub all_values_const_name: Option<Cow<'static, str>>,
286
287 /// If present, structs representing the values associated with
288 /// enum variants will also be generated.
289 ///
290 /// The [`ValuesStructOptions`] defines further options for how
291 /// they are generated.
292 pub values_struct: Option<ValuesStructOptions>,
293
294 /// If present, generates a method with this name for fetching
295 /// the value associated with an enum variant.
296 pub get_value_fn_name: Option<Cow<'static, str>>,
297}
298
299impl EnumOptions {
300 /// # Examples
301 /// ```
302 /// # use edres_core::options::*;
303 /// assert_eq!(EnumOptions::new(), EnumOptions {
304 /// derived_traits: vec![
305 /// "Debug".into(),
306 /// "Clone".into(),
307 /// "Copy".into(),
308 /// "PartialEq".into(),
309 /// "Eq".into(),
310 /// "Hash".into(),
311 /// ].into(),
312 /// impl_default: true,
313 /// impl_display: true,
314 /// impl_from_str: true,
315 /// all_variants_const_name: Some("ALL".into()),
316 /// all_values_const_name: Some("VALUES".into()),
317 /// values_struct: Some(ValuesStructOptions::new()),
318 /// get_value_fn_name: Some("get".into()),
319 /// });
320 /// ```
321 pub const fn new() -> EnumOptions {
322 EnumOptions {
323 derived_traits: Cow::Borrowed(&[
324 Cow::Borrowed("Debug"),
325 Cow::Borrowed("Clone"),
326 Cow::Borrowed("Copy"),
327 Cow::Borrowed("PartialEq"),
328 Cow::Borrowed("Eq"),
329 Cow::Borrowed("Hash"),
330 ]),
331 impl_default: true,
332 impl_display: true,
333 impl_from_str: true,
334 all_variants_const_name: Some(Cow::Borrowed("ALL")),
335 all_values_const_name: Some(Cow::Borrowed("VALUES")),
336 values_struct: Some(ValuesStructOptions::new()),
337 get_value_fn_name: Some(Cow::Borrowed("get")),
338 }
339 }
340
341 /// # Examples
342 /// ```
343 /// # use edres_core::options::*;
344 /// assert_eq!(EnumOptions::minimal(), EnumOptions {
345 /// derived_traits: vec![].into(),
346 /// impl_default: false,
347 /// impl_display: false,
348 /// impl_from_str: false,
349 /// all_variants_const_name: None,
350 /// all_values_const_name: None,
351 /// values_struct: None,
352 /// get_value_fn_name: None,
353 /// });
354 /// ```
355 pub const fn minimal() -> EnumOptions {
356 EnumOptions {
357 derived_traits: Cow::Borrowed(&[]),
358 impl_default: false,
359 impl_display: false,
360 impl_from_str: false,
361 all_variants_const_name: None,
362 all_values_const_name: None,
363 values_struct: None,
364 get_value_fn_name: None,
365 }
366 }
367}
368
369impl Default for EnumOptions {
370 /// # Examples
371 /// ```
372 /// # use edres_core::options::*;
373 /// assert_eq!(EnumOptions::default(), EnumOptions::new());
374 /// ```
375 fn default() -> Self {
376 Self::new()
377 }
378}
379
380/// Options specific to how `edres` should generate structs for
381/// values associated with enum variants.
382#[derive(Debug, Clone, PartialEq, Eq)]
383pub struct ValuesStructOptions {
384 /// If present, this will be the name of the struct generated
385 /// for the values corresponding to the enum variants.
386 pub struct_name: Option<Cow<'static, str>>,
387
388 /// The options for generating structs based on values
389 /// associated with the enum.
390 pub struct_options: StructOptions,
391}
392
393impl ValuesStructOptions {
394 /// # Examples
395 /// ```
396 /// # use edres_core::options::*;
397 /// assert_eq!(ValuesStructOptions::new(), ValuesStructOptions {
398 /// struct_name: None,
399 /// struct_options: StructOptions::new(),
400 /// });
401 /// ```
402 pub const fn new() -> Self {
403 ValuesStructOptions {
404 struct_name: None,
405 struct_options: StructOptions::new(),
406 }
407 }
408
409 /// # Examples
410 /// ```
411 /// # use edres_core::options::*;
412 /// assert_eq!(ValuesStructOptions::minimal(), ValuesStructOptions {
413 /// struct_name: None,
414 /// struct_options: StructOptions::minimal(),
415 /// });
416 /// ```
417 pub const fn minimal() -> Self {
418 ValuesStructOptions {
419 struct_name: None,
420 struct_options: StructOptions::minimal(),
421 }
422 }
423}
424
425impl Default for ValuesStructOptions {
426 /// # Examples
427 /// ```
428 /// # use edres_core::options::*;
429 /// assert_eq!(ValuesStructOptions::default(), ValuesStructOptions::new());
430 /// ```
431 fn default() -> Self {
432 Self::new()
433 }
434}
435
436/// Options specific to how `edres` should handle input files.
437#[derive(Debug, Clone, PartialEq, Eq)]
438pub struct FilesOptions {
439 /// If present, generates a const with this name containing
440 /// a slice of the paths of the files used to generate the
441 /// output.
442 pub file_paths_const_name: Option<Cow<'static, str>>,
443
444 /// If present, generates a method which returns the path
445 /// associated with an enum variant.
446 pub get_path_fn_name: Option<Cow<'static, str>>,
447
448 /// If present, generates a const with this name containing
449 /// a slice of the string contents of each file used to
450 /// generate the output.
451 pub file_strings_const_name: Option<Cow<'static, str>>,
452
453 /// If present, generates a method which returns the string
454 /// contents associated with an enum variant.
455 pub get_string_fn_name: Option<Cow<'static, str>>,
456
457 /// If present, generates a const with this name containing
458 /// a slice of the binary contents of each file used to
459 /// generate the output.
460 pub file_bytes_const_name: Option<Cow<'static, str>>,
461
462 /// If present, generates a method which returns the bytes
463 /// associated with an enum variant.
464 pub get_bytes_fn_name: Option<Cow<'static, str>>,
465}
466
467impl FilesOptions {
468 /// # Examples
469 /// ```
470 /// # use edres_core::options::*;
471 /// assert_eq!(FilesOptions::new(), FilesOptions {
472 /// file_paths_const_name: Some("FILE_PATHS".into()),
473 /// get_path_fn_name: Some("path".into()),
474 /// file_strings_const_name: None,
475 /// get_string_fn_name: None,
476 /// file_bytes_const_name: None,
477 /// get_bytes_fn_name: None,
478 /// });
479 /// ```
480 pub const fn new() -> FilesOptions {
481 FilesOptions {
482 file_paths_const_name: Some(Cow::Borrowed("FILE_PATHS")),
483 get_path_fn_name: Some(Cow::Borrowed("path")),
484 file_strings_const_name: None,
485 get_string_fn_name: None,
486 file_bytes_const_name: None,
487 get_bytes_fn_name: None,
488 }
489 }
490
491 /// # Examples
492 /// ```
493 /// # use edres_core::options::*;
494 /// assert_eq!(FilesOptions::minimal(), FilesOptions {
495 /// file_paths_const_name: None,
496 /// get_path_fn_name: None,
497 /// file_strings_const_name: None,
498 /// get_string_fn_name: None,
499 /// file_bytes_const_name: None,
500 /// get_bytes_fn_name: None,
501 /// });
502 /// ```
503 pub const fn minimal() -> FilesOptions {
504 FilesOptions {
505 file_paths_const_name: None,
506 get_path_fn_name: None,
507 file_strings_const_name: None,
508 get_string_fn_name: None,
509 file_bytes_const_name: None,
510 get_bytes_fn_name: None,
511 }
512 }
513
514 /// # Examples
515 /// ```
516 /// # use edres_core::options::*;
517 /// assert_eq!(FilesOptions::file_bytes(), FilesOptions {
518 /// file_paths_const_name: None,
519 /// get_path_fn_name: None,
520 /// file_strings_const_name: None,
521 /// get_string_fn_name: None,
522 /// file_bytes_const_name: Some("FILE_BYTES".into()),
523 /// get_bytes_fn_name: Some("bytes".into()),
524 /// });
525 /// ```
526 pub const fn file_bytes() -> FilesOptions {
527 FilesOptions {
528 file_paths_const_name: None,
529 get_path_fn_name: None,
530 file_strings_const_name: None,
531 get_string_fn_name: None,
532 file_bytes_const_name: Some(Cow::Borrowed("FILE_BYTES")),
533 get_bytes_fn_name: Some(Cow::Borrowed("bytes")),
534 }
535 }
536
537 /// # Examples
538 /// ```
539 /// # use edres_core::options::*;
540 /// assert_eq!(FilesOptions::file_strings(), FilesOptions {
541 /// file_paths_const_name: None,
542 /// get_path_fn_name: None,
543 /// file_strings_const_name: Some("FILE_STRINGS".into()),
544 /// get_string_fn_name: Some("string".into()),
545 /// file_bytes_const_name: None,
546 /// get_bytes_fn_name: None,
547 /// });
548 /// ```
549 pub const fn file_strings() -> FilesOptions {
550 FilesOptions {
551 file_paths_const_name: None,
552 get_path_fn_name: None,
553 file_strings_const_name: Some(Cow::Borrowed("FILE_STRINGS")),
554 get_string_fn_name: Some(Cow::Borrowed("string")),
555 file_bytes_const_name: None,
556 get_bytes_fn_name: None,
557 }
558 }
559}
560
561impl Default for FilesOptions {
562 /// # Examples
563 /// ```
564 /// # use edres_core::options::*;
565 /// assert_eq!(FilesOptions::default(), FilesOptions::new());
566 /// ```
567 fn default() -> Self {
568 FilesOptions::new()
569 }
570}
571
572/// Options specific to how `edres` should handle its output.
573#[derive(Debug, Clone, PartialEq, Eq)]
574pub struct OutputOptions {
575 /// If true, missing destination directories will be created
576 /// on output.
577 pub create_dirs: bool,
578
579 /// If true, files will only be written if they have changed.
580 ///
581 /// Generation will still take place. This is not an
582 /// optimization, but it can be used to avoid unintentionally
583 /// triggering any processes that watch for changes. (For
584 /// example, `cargo watch`.)
585 pub write_only_if_changed: bool,
586}
587
588impl OutputOptions {
589 /// # Examples
590 /// ```
591 /// # use edres_core::options::*;
592 /// assert_eq!(OutputOptions::new(), OutputOptions {
593 /// create_dirs: true,
594 /// write_only_if_changed: true,
595 /// });
596 /// ```
597 pub const fn new() -> Self {
598 OutputOptions {
599 create_dirs: true,
600 write_only_if_changed: true,
601 }
602 }
603}
604
605impl Default for OutputOptions {
606 /// # Examples
607 /// ```
608 /// # use edres_core::options::*;
609 /// assert_eq!(OutputOptions::default(), OutputOptions::new());
610 /// ```
611 fn default() -> Self {
612 Self::new()
613 }
614}
615
616/// Options for serde support.
617#[derive(Debug, Copy, Clone, PartialEq, Eq)]
618pub enum SerdeSupport {
619 /// Do not derive any serde traits for the struct.
620 No,
621
622 /// Derive `Serialize` and `Deserialize` for the struct.
623 Yes,
624
625 /// Derive any combination of `Serialize` and `Deserialize`
626 /// for the struct.
627 Mixed { serialize: bool, deserialize: bool },
628}
629
630impl SerdeSupport {
631 pub(crate) fn should_derive_ser_de(self) -> Option<(bool, bool)> {
632 match self {
633 Self::No => None,
634 Self::Yes => Some((true, true)),
635 Self::Mixed {
636 serialize,
637 deserialize,
638 } => {
639 if !(serialize || deserialize) {
640 None
641 } else {
642 Some((serialize, deserialize))
643 }
644 }
645 }
646 }
647}
648
649impl Default for SerdeSupport {
650 /// # Examples
651 /// ```
652 /// # use edres_core::options::*;
653 /// assert_eq!(SerdeSupport::default(), SerdeSupport::No);
654 /// ```
655 fn default() -> Self {
656 Self::No
657 }
658}
659
660/// Used to specify the default size of floating point values
661/// (providing they fit within the given size).
662#[derive(Debug, Clone, Copy, PartialEq, Eq)]
663pub enum FloatSize {
664 F32,
665 F64,
666}
667
668/// Used to specify the default size of integer values
669/// (providing they fit within the given size).
670#[derive(Debug, Clone, Copy, PartialEq, Eq)]
671pub enum IntSize {
672 I8,
673 I16,
674 I32,
675 I64,
676 I128,
677 ISize,
678}