1use serde::Deserialize;
2
3use crate::policy::FlagStyle;
4use crate::verdict::SafetyLevel;
5
6#[derive(Debug, Deserialize)]
7pub(super) struct TomlFile {
8 pub command: Vec<TomlCommand>,
9}
10
11#[derive(Debug, Deserialize)]
12pub(super) struct TomlCommand {
13 pub name: String,
14 #[serde(default)]
15 pub description: Option<String>,
16 #[serde(default)]
17 pub candidate: Option<bool>,
18 #[serde(default)]
19 pub aliases: Vec<String>,
20 #[serde(default)]
21 pub url: String,
22 #[serde(default)]
23 pub level: Option<TomlLevel>,
24 #[serde(default)]
25 pub bare: Option<bool>,
26 #[serde(default)]
27 pub max_positional: Option<usize>,
28 #[serde(default)]
29 pub positional_style: Option<bool>,
30 #[serde(default)]
31 pub numeric_dash: Option<bool>,
32 #[serde(default)]
33 pub standalone: Vec<String>,
34 #[serde(default)]
35 pub valued: Vec<String>,
36 #[serde(default)]
37 pub bare_flags: Vec<String>,
38 #[serde(default)]
39 pub sub: Vec<TomlSub>,
40 #[serde(default)]
41 pub handler: Option<String>,
42 #[serde(default)]
43 pub doc_body: Option<String>,
44 #[serde(default)]
45 pub require_any: Vec<String>,
46 #[serde(default)]
47 pub first_arg: Vec<String>,
48 #[serde(default)]
49 pub wrapper: Option<TomlWrapper>,
50 #[serde(default)]
51 pub write_flags: Vec<String>,
52 #[serde(default)]
53 pub researched_version: Option<String>,
54 #[serde(default)]
59 pub examples_safe: Vec<String>,
60 #[serde(default)]
61 pub examples_denied: Vec<String>,
62}
63
64#[derive(Debug, Deserialize)]
65pub(super) struct TomlWrapper {
66 #[serde(default)]
67 pub standalone: Vec<String>,
68 #[serde(default)]
69 pub valued: Vec<String>,
70 #[serde(default)]
71 pub positional_skip: Option<usize>,
72 #[serde(default)]
73 pub separator: Option<String>,
74 #[serde(default)]
75 pub bare_ok: Option<bool>,
76}
77
78#[derive(Debug, Deserialize)]
79pub(super) struct TomlSub {
80 pub name: String,
81 #[serde(default)]
82 pub candidate: Option<bool>,
83 #[serde(default)]
84 pub aliases: Vec<String>,
85 #[serde(default)]
86 pub level: Option<TomlLevel>,
87 #[serde(default)]
88 pub bare: Option<bool>,
89 #[serde(default)]
90 pub max_positional: Option<usize>,
91 #[serde(default)]
92 pub positional_style: Option<bool>,
93 #[serde(default)]
94 pub numeric_dash: Option<bool>,
95 #[serde(default)]
96 pub standalone: Vec<String>,
97 #[serde(default)]
98 pub valued: Vec<String>,
99 #[serde(default)]
100 pub guard: Option<String>,
101 #[serde(default)]
102 pub guard_short: Option<String>,
103 #[serde(default)]
104 pub allow_all: Option<bool>,
105 #[serde(default)]
106 pub sub: Vec<TomlSub>,
107 #[serde(default)]
108 pub nested_bare: Option<bool>,
109 #[serde(default)]
110 pub require_any: Vec<String>,
111 #[serde(default)]
112 pub first_arg: Vec<String>,
113 #[serde(default)]
114 pub write_flags: Vec<String>,
115 #[serde(default)]
116 pub delegate_after: Option<String>,
117 #[serde(default)]
118 pub delegate_skip: Option<usize>,
119 #[serde(default)]
120 pub handler: Option<String>,
121 #[serde(default)]
122 pub doc_body: Option<String>,
123}
124
125#[derive(Debug, Clone, Copy, Deserialize)]
126pub(super) enum TomlLevel {
127 Inert,
128 SafeRead,
129 SafeWrite,
130}
131
132impl From<TomlLevel> for SafetyLevel {
133 fn from(l: TomlLevel) -> Self {
134 match l {
135 TomlLevel::Inert => SafetyLevel::Inert,
136 TomlLevel::SafeRead => SafetyLevel::SafeRead,
137 TomlLevel::SafeWrite => SafetyLevel::SafeWrite,
138 }
139 }
140}
141
142#[derive(Debug)]
143pub struct CommandSpec {
144 pub name: String,
145 pub description: String,
146 pub aliases: Vec<String>,
147 pub url: String,
148 pub category: String,
149 pub researched_version: Option<String>,
156 pub examples_safe: Vec<String>,
159 pub examples_denied: Vec<String>,
163 pub(super) kind: DispatchKind,
164}
165
166#[derive(Debug, Clone)]
167pub(super) struct SubSpec {
168 pub name: String,
169 pub kind: DispatchKind,
170}
171
172#[derive(Debug, Clone)]
173pub(super) enum DispatchKind {
174 Policy {
175 policy: OwnedPolicy,
176 level: SafetyLevel,
177 },
178 FirstArg {
179 patterns: Vec<String>,
180 level: SafetyLevel,
181 },
182 RequireAny {
183 require_any: Vec<String>,
184 policy: OwnedPolicy,
185 level: SafetyLevel,
186 accept_bare_help: bool,
187 },
188 Branching {
189 subs: Vec<SubSpec>,
190 bare_flags: Vec<String>,
191 bare_ok: bool,
192 pre_standalone: Vec<String>,
193 pre_valued: Vec<String>,
194 first_arg: Vec<String>,
195 first_arg_level: SafetyLevel,
196 },
197 WriteFlagged {
198 policy: OwnedPolicy,
199 base_level: SafetyLevel,
200 write_flags: Vec<String>,
201 },
202 DelegateAfterSeparator {
203 separator: String,
204 },
205 DelegateSkip {
206 skip: usize,
207 },
208 Wrapper {
209 standalone: Vec<String>,
210 valued: Vec<String>,
211 positional_skip: usize,
212 separator: Option<String>,
213 bare_ok: bool,
214 },
215 Custom {
216 #[allow(dead_code)]
217 handler_name: String,
218 doc_body: Option<String>,
219 },
220}
221
222#[derive(Debug, Clone)]
223pub struct OwnedPolicy {
224 pub standalone: Vec<String>,
225 pub valued: Vec<String>,
226 pub bare: bool,
227 pub max_positional: Option<usize>,
228 pub flag_style: FlagStyle,
229 pub numeric_dash: bool,
230}