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