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 },
147 Wrapper {
148 standalone: Vec<String>,
149 valued: Vec<String>,
150 positional_skip: usize,
151 separator: Option<String>,
152 bare_ok: bool,
153 },
154 Custom {
155 #[allow(dead_code)]
156 handler_name: String,
157 },
158}
159
160#[derive(Debug)]
161pub(super) struct SubSpec {
162 pub name: String,
163 pub kind: SubKind,
164}
165
166#[derive(Debug)]
167pub(super) enum SubKind {
168 Policy {
169 policy: OwnedPolicy,
170 level: SafetyLevel,
171 },
172 Guarded {
173 guard_long: String,
174 guard_short: Option<String>,
175 policy: OwnedPolicy,
176 level: SafetyLevel,
177 },
178 Nested {
179 subs: Vec<SubSpec>,
180 allow_bare: bool,
181 },
182 AllowAll {
183 level: SafetyLevel,
184 },
185 WriteFlagged {
186 policy: OwnedPolicy,
187 base_level: SafetyLevel,
188 write_flags: Vec<String>,
189 },
190 FirstArgFilter {
191 patterns: Vec<String>,
192 level: SafetyLevel,
193 },
194 RequireAny {
195 require_any: Vec<String>,
196 policy: OwnedPolicy,
197 level: SafetyLevel,
198 },
199 DelegateAfterSeparator {
200 separator: String,
201 },
202 DelegateSkip {
203 skip: usize,
204 #[allow(dead_code)]
205 doc: String,
206 },
207 Custom {
208 #[allow(dead_code)]
209 handler_name: String,
210 },
211}
212
213#[derive(Debug)]
214pub struct OwnedPolicy {
215 pub standalone: Vec<String>,
216 pub valued: Vec<String>,
217 pub bare: bool,
218 pub max_positional: Option<usize>,
219 pub flag_style: FlagStyle,
220}