1use clap::{arg, Arg, ArgAction, Command};
2use criterion::{criterion_group, criterion_main, Criterion};
3
4static OPT3_VALS: [&str; 2] = ["fast", "slow"];
5static POS3_VALS: [&str; 2] = ["vi", "emacs"];
6
7macro_rules! create_app {
8    () => {{
9        Command::new("claptests")
10            .version("0.1")
11            .about("tests clap library")
12            .author("Kevin K. <kbknapp@gmail.com>")
13            .arg(arg!(-o --option <opt> ... "tests options"))
14            .arg(arg!([positional] "tests positionals"))
15            .arg(arg!(-f --flag ... "tests flags").global(true))
16            .args([
17                arg!(flag2: -F "tests flags with exclusions")
18                    .conflicts_with("flag")
19                    .requires("option2"),
20                arg!(option2: --"long-option-2" <option2> "tests long options with exclusions")
21                    .conflicts_with("option")
22                    .requires("positional2"),
23                arg!([positional2] "tests positionals with exclusions"),
24                arg!(-O --Option <option3> "tests options with specific value sets")
25                    .value_parser(OPT3_VALS),
26                arg!([positional3] ... "tests positionals with specific values")
27                    .value_parser(POS3_VALS),
28                arg!(--multvals <s> "Tests multiple values not mult occs").value_names(["one", "two"]),
29                arg!(
30                    --multvalsmo <s> "Tests multiple values, not mult occs"
31                ).required(false).value_names(["one", "two"]),
32                arg!(--minvals2 <minvals> ... "Tests 2 min vals").num_args(2..),
33                arg!(--maxvals3 <maxvals> ... "Tests 3 max vals").num_args(1..=3),
34            ])
35            .subcommand(
36                Command::new("subcmd")
37                    .about("tests subcommands")
38                    .version("0.1")
39                    .author("Kevin K. <kbknapp@gmail.com>")
40                    .arg(arg!(-o --option <scoption> ... "tests options"))
41                    .arg(arg!([scpositional] "tests positionals"))
42            )
43    }};
44}
45
46pub fn build_from_builder(c: &mut Criterion) {
47    c.bench_function("build_from_builder", |b| {
48        b.iter(|| {
49            Command::new("claptests")
50                .version("0.1")
51                .about("tests clap library")
52                .author("Kevin K. <kbknapp@gmail.com>")
53                .arg(
54                    Arg::new("opt")
55                        .help("tests options")
56                        .short('o')
57                        .long("option")
58                        .num_args(1..)
59                        .action(ArgAction::Append),
60                )
61                .arg(Arg::new("positional").help("tests positionals").index(1))
62                .arg(
63                    Arg::new("flag")
64                        .short('f')
65                        .help("tests flags")
66                        .long("flag")
67                        .global(true)
68                        .action(ArgAction::Count),
69                )
70                .arg(
71                    Arg::new("flag2")
72                        .short('F')
73                        .help("tests flags with exclusions")
74                        .action(ArgAction::SetTrue)
75                        .conflicts_with("flag")
76                        .requires("option2"),
77                )
78                .arg(
79                    Arg::new("option2")
80                        .help("tests long options with exclusions")
81                        .conflicts_with("option")
82                        .requires("positional2")
83                        .action(ArgAction::Set)
84                        .long("long-option-2"),
85                )
86                .arg(
87                    Arg::new("positional2")
88                        .index(3)
89                        .help("tests positionals with exclusions"),
90                )
91                .arg(
92                    Arg::new("option3")
93                        .short('O')
94                        .long("Option")
95                        .action(ArgAction::Set)
96                        .help("tests options with specific value sets")
97                        .value_parser(OPT3_VALS),
98                )
99                .arg(
100                    Arg::new("positional3")
101                        .num_args(1..)
102                        .help("tests positionals with specific values")
103                        .index(4)
104                        .value_parser(POS3_VALS),
105                )
106                .arg(
107                    Arg::new("multvals")
108                        .long("multvals")
109                        .help("Tests multiple values, not mult occs")
110                        .value_names(["one", "two"]),
111                )
112                .arg(
113                    Arg::new("multvalsmo")
114                        .long("multvalsmo")
115                        .action(ArgAction::Append)
116                        .help("Tests multiple values, not mult occs")
117                        .value_names(["one", "two"]),
118                )
119                .arg(
120                    Arg::new("minvals")
121                        .long("minvals2")
122                        .action(ArgAction::Append)
123                        .help("Tests 2 min vals")
124                        .num_args(2..),
125                )
126                .arg(
127                    Arg::new("maxvals")
128                        .long("maxvals3")
129                        .action(ArgAction::Append)
130                        .help("Tests 3 max vals")
131                        .num_args(1..=3),
132                )
133                .subcommand(
134                    Command::new("subcmd")
135                        .about("tests subcommands")
136                        .version("0.1")
137                        .author("Kevin K. <kbknapp@gmail.com>")
138                        .arg(
139                            Arg::new("scoption")
140                                .short('o')
141                                .long("option")
142                                .num_args(1..)
143                                .action(ArgAction::Append)
144                                .help("tests options"),
145                        )
146                        .arg(Arg::new("scpositional").index(1).help("tests positionals")),
147                )
148        })
149    });
150}
151
152pub fn parse_complex(c: &mut Criterion) {
153    c.bench_function("parse_complex", |b| {
154        b.iter(|| create_app!().get_matches_from(vec![""]))
155    });
156}
157
158pub fn parse_complex_with_flag(c: &mut Criterion) {
159    c.bench_function("parse_complex_with_flag", |b| {
160        b.iter(|| create_app!().get_matches_from(vec!["myprog", "-f"]))
161    });
162}
163
164pub fn parse_complex_with_opt(c: &mut Criterion) {
165    c.bench_function("parse_complex_with_opt", |b| {
166        b.iter(|| create_app!().get_matches_from(vec!["myprog", "-o", "option1"]))
167    });
168}
169
170pub fn parse_complex_with_pos(c: &mut Criterion) {
171    c.bench_function("parse_complex_with_pos", |b| {
172        b.iter(|| create_app!().get_matches_from(vec!["myprog", "arg1"]))
173    });
174}
175
176pub fn parse_complex_with_sc(c: &mut Criterion) {
177    c.bench_function("parse_complex_with_sc", |b| {
178        b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd"]))
179    });
180}
181
182pub fn parse_complex_with_sc_flag(c: &mut Criterion) {
183    c.bench_function("parse_complex_with_sc_flag", |b| {
184        b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd", "-f"]))
185    });
186}
187
188pub fn parse_complex_with_sc_opt(c: &mut Criterion) {
189    c.bench_function("parse_complex_with_sc_opt", |b| {
190        b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd", "-o", "option1"]))
191    });
192}
193
194pub fn parse_complex_with_sc_pos(c: &mut Criterion) {
195    c.bench_function("parse_complex_with_sc_pos", |b| {
196        b.iter(|| create_app!().get_matches_from(vec!["myprog", "subcmd", "arg1"]))
197    });
198}
199
200pub fn parse_complex1(c: &mut Criterion) {
201    c.bench_function("parse_complex1", |b| {
202        b.iter(|| {
203            create_app!().get_matches_from(vec![
204                "myprog",
205                "-ff",
206                "-o",
207                "option1",
208                "arg1",
209                "-O",
210                "fast",
211                "arg2",
212                "--multvals",
213                "one",
214                "two",
215                "emacs",
216            ])
217        })
218    });
219}
220
221pub fn parse_complex2(c: &mut Criterion) {
222    c.bench_function("parse_complex2", |b| {
223        b.iter(|| {
224            create_app!().get_matches_from(vec![
225                "myprog",
226                "arg1",
227                "-f",
228                "arg2",
229                "--long-option-2",
230                "some",
231                "-O",
232                "slow",
233                "--multvalsmo",
234                "one",
235                "two",
236                "--minvals2",
237                "3",
238                "2",
239                "1",
240            ])
241        })
242    });
243}
244
245pub fn parse_args_negate_scs(c: &mut Criterion) {
246    c.bench_function("parse_args_negate_scs", |b| {
247        b.iter(|| {
248            create_app!()
249                .args_conflicts_with_subcommands(true)
250                .get_matches_from(vec![
251                    "myprog",
252                    "arg1",
253                    "-f",
254                    "arg2",
255                    "--long-option-2",
256                    "some",
257                    "-O",
258                    "slow",
259                    "--multvalsmo",
260                    "one",
261                    "two",
262                    "--minvals2",
263                    "3",
264                    "2",
265                    "1",
266                ])
267        })
268    });
269}
270
271pub fn parse_complex_with_sc_complex(c: &mut Criterion) {
272    c.bench_function("parse_complex_with_sc_complex", |b| {
273        b.iter(|| {
274            create_app!().get_matches_from(vec!["myprog", "subcmd", "-f", "-o", "option1", "arg1"])
275        })
276    });
277}
278
279criterion_group!(
280    benches,
281    build_from_builder,
282    parse_complex,
283    parse_complex_with_flag,
284    parse_complex_with_opt,
285    parse_complex_with_pos,
286    parse_complex_with_sc,
287    parse_complex_with_sc_flag,
288    parse_complex_with_sc_opt,
289    parse_complex_with_sc_pos,
290    parse_complex1,
291    parse_complex2,
292    parse_args_negate_scs,
293    parse_complex_with_sc_complex
294);
295
296criterion_main!(benches);
297