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