1use serde::{Deserialize, Serialize};
2
3use crate::Chip;
4
5#[derive(Clone, Serialize, Deserialize, Debug)]
6pub struct GeneratorOption {
7 pub name: String,
8 pub display_name: String,
9 #[serde(default)]
11 pub selection_group: String,
12 #[serde(default)]
13 pub help: String,
14 #[serde(default)]
15 pub requires: Vec<String>,
16 #[serde(default)]
17 pub chips: Vec<Chip>,
18}
19
20impl GeneratorOption {
21 pub fn options(&self) -> Vec<String> {
22 vec![self.name.to_string()]
23 }
24}
25
26#[derive(Clone, Serialize, Deserialize, Debug)]
27pub struct GeneratorOptionCategory {
28 pub name: String,
29 pub display_name: String,
30 #[serde(default)]
31 pub help: String,
32 #[serde(default)]
33 pub requires: Vec<String>,
34 #[serde(default)]
35 pub options: Vec<GeneratorOptionItem>,
36}
37
38impl GeneratorOptionCategory {
39 pub fn options(&self) -> Vec<String> {
40 let mut res = Vec::new();
41 for option in self.options.iter() {
42 res.extend(option.options());
43 }
44 res
45 }
46}
47
48#[derive(Clone, Serialize, Deserialize, Debug)]
49pub enum GeneratorOptionItem {
50 Category(GeneratorOptionCategory),
51 Option(GeneratorOption),
52}
53
54impl GeneratorOptionItem {
55 pub fn title(&self) -> &str {
56 match self {
57 GeneratorOptionItem::Category(category) => category.display_name.as_str(),
58 GeneratorOptionItem::Option(option) => option.display_name.as_str(),
59 }
60 }
61
62 pub fn name(&self) -> &str {
63 match self {
64 GeneratorOptionItem::Category(category) => category.name.as_str(),
65 GeneratorOptionItem::Option(option) => option.name.as_str(),
66 }
67 }
68
69 pub fn options(&self) -> Vec<String> {
70 match self {
71 GeneratorOptionItem::Category(category) => category.options(),
72 GeneratorOptionItem::Option(option) => option.options(),
73 }
74 }
75
76 pub fn is_category(&self) -> bool {
77 matches!(self, GeneratorOptionItem::Category(_))
78 }
79
80 pub fn chips(&self) -> &[Chip] {
81 match self {
82 GeneratorOptionItem::Category(_) => &[],
83 GeneratorOptionItem::Option(option) => option.chips.as_slice(),
84 }
85 }
86
87 pub fn requires(&self) -> &[String] {
88 match self {
89 GeneratorOptionItem::Category(category) => category.requires.as_slice(),
90 GeneratorOptionItem::Option(option) => option.requires.as_slice(),
91 }
92 }
93
94 pub fn help(&self) -> &str {
95 match self {
96 GeneratorOptionItem::Category(category) => &category.help,
97 GeneratorOptionItem::Option(option) => &option.help,
98 }
99 }
100}
101
102#[derive(Clone, Serialize, Deserialize)]
103pub struct Template {
104 pub options: Vec<GeneratorOptionItem>,
105}
106
107impl Template {
108 pub fn all_options(&self) -> Vec<&GeneratorOption> {
109 all_options_in(&self.options)
110 }
111}
112
113fn all_options_in(options: &[GeneratorOptionItem]) -> Vec<&GeneratorOption> {
114 options
115 .iter()
116 .flat_map(|o| match o {
117 GeneratorOptionItem::Option(option) => vec![option],
118 GeneratorOptionItem::Category(category) => all_options_in(&category.options),
119 })
120 .collect()
121}