runner/
cli.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![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
11/// # Errors
12/// Returns an error if the arguments are invalid.
13/// # Panics
14/// Panics if the arguments cannot be read.
15pub 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}