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}