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