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