1#![deny(clippy::all, clippy::pedantic)]
5
6use clap::error::ErrorKind;
7use clap::{Command, arg, crate_version, value_parser};
8use std::io::IsTerminal;
9use std::{ffi::OsString, path::PathBuf};
10
11pub fn main<I, T>(args: Option<I>) -> Result<(), String>
16where
17 I: IntoIterator<Item = T>,
18 T: Into<OsString> + Clone,
19{
20 let cmd = Command::new("qir-runner").args(&[
21 arg!(-f --file <PATH> "Path to the QIR file to run. If not provided or '-', standard input will be read.")
22 .value_parser(value_parser!(PathBuf)),
23 arg!(-e --entrypoint <NAME> "Name of the entry point function to execute"),
24 arg!(-s --shots <NUM> "The number of times to repeat the execution of the chosen entry point in the program")
25 .value_parser(value_parser!(u32))
26 .default_value("1"),
27 arg!(-r --rngseed <NUM> "The value to use when seeding the random number generator used for quantum simulation")
28 .value_parser(value_parser!(u64))
29 ]).version(crate_version!());
30 let mut help_cmd = cmd.clone();
31 let matches = match args {
32 Some(args) => cmd.try_get_matches_from(args),
33 None => cmd.try_get_matches(),
34 };
35 match matches {
36 Err(e) => {
37 let msg = e.to_string();
38 match e.kind() {
39 ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => {
40 eprint!("{msg}");
41 Ok(())
42 }
43 _ => Err(msg),
44 }
45 }
46 Ok(matches) => {
47 let file = matches.get_one::<PathBuf>("file").and_then(|path| {
48 if path.as_os_str() == "-" {
49 None
50 } else {
51 Some(path)
52 }
53 });
54 let entry_point = matches
55 .get_one::<String>("entrypoint")
56 .map(std::string::String::as_str);
57 let shots = *matches
58 .get_one::<u32>("shots")
59 .expect("Shots is required or should have a default value");
60 let rng_seed = matches
61 .try_get_one::<u64>("rngseed")
62 .map_or(None, Option::<&u64>::copied);
63 let output = &mut std::io::stdout();
64
65 if let Some(path) = file {
66 crate::run_file(path, entry_point, shots, rng_seed, output)
67 } else {
68 if std::io::stdin().is_terminal() {
69 return help_cmd.print_help().map_err(|e| e.to_string());
70 }
71 crate::run_input(
72 &mut std::io::stdin().lock(),
73 entry_point,
74 shots,
75 rng_seed,
76 output,
77 )
78 }
79 }
80 }
81}