1#![deny(clippy::all, clippy::pedantic)]
5
6use clap::error::ErrorKind;
7use clap::{arg, crate_version, value_parser, Command};
8use std::env::{self, ArgsOs};
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> "(Required) Path to the QIR file to run")
22 .value_parser(value_parser!(PathBuf))
23 .required(true),
24 arg!(-e --entrypoint <NAME> "Name of the entry point function to execute"),
25 arg!(-s --shots <NUM> "The number of times to repeat the execution of the chosen entry point in the program")
26 .value_parser(value_parser!(u32))
27 .default_value("1"),
28 arg!(-r --rngseed <NUM> "The value to use when seeding the random number generator used for quantum simulation")
29 .value_parser(value_parser!(u64))
30 ]).version(crate_version!());
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) => crate::run_file(
47 matches
48 .get_one::<PathBuf>("file")
49 .expect("File path is required"),
50 matches
51 .get_one::<String>("entrypoint")
52 .map(std::string::String::as_str),
53 *matches
54 .get_one::<u32>("shots")
55 .expect("Shots is required or should have a default value"),
56 matches
57 .try_get_one::<u64>("rngseed")
58 .map_or(None, Option::<&u64>::copied),
59 &mut std::io::stdout(),
60 ),
61 }
62}