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