use std::{
env,
path::{Path, PathBuf},
sync::LazyLock,
};
struct Arguments {
args: Vec<String>,
args_group1: Vec<String>,
args_group2: Vec<String>,
current_exe_path: PathBuf,
rap_clean: bool,
}
impl Arguments {
fn get_arg_flag_value(&self, name: &str) -> Option<&str> {
let mut args = self.args_group1.iter();
while let Some(arg) = args.next() {
if !arg.starts_with(name) {
continue;
}
let suffix = &arg[name.len()..];
if suffix.is_empty() {
return args.next().map(|x| x.as_str());
} else if let Some(arg) = suffix.strip_prefix('=') {
return Some(arg);
}
}
None
}
fn new() -> Self {
fn rap_clean() -> bool {
match env::var("RAP_CLEAN")
.ok()
.map(|s| s.trim().to_ascii_lowercase())
.as_deref()
{
Some("false") => false,
_ => true, }
}
let args: Vec<_> = env::args().collect();
let path = env::current_exe().expect("Current executable path invalid.");
rap_trace!("Current exe: {path:?}\tReceived args: {args:?}");
let [args_group1, args_group2] = split_args_by_double_dash(&args);
Arguments {
args,
args_group1,
args_group2,
current_exe_path: path,
rap_clean: rap_clean(),
}
}
fn is_current_compile_crate(&self) -> bool {
let mut args = self.args_group1.iter();
let entry_path = match args.find(|s| s.ends_with(".rs")) {
Some(path) => Path::new(path),
None => return false,
};
entry_path.is_relative()
|| entry_path.ends_with("lib/rustlib/src/rust/library/std/src/lib.rs")
|| entry_path.ends_with("lib/rustlib/src/rust/library/core/src/lib.rs")
|| entry_path.ends_with("lib/rustlib/src/rust/library/alloc/src/lib.rs")
}
}
pub fn rap_clean() -> bool {
ARGS.rap_clean
}
fn split_args_by_double_dash(args: &[String]) -> [Vec<String>; 2] {
let mut args = args.iter().skip(2).map(|arg| arg.to_owned());
let rap_args = args.by_ref().take_while(|arg| *arg != "--").collect();
let cargo_args = args.collect();
[rap_args, cargo_args]
}
static ARGS: LazyLock<Arguments> = LazyLock::new(Arguments::new);
pub fn get_arg_flag_value(name: &str) -> Option<&'static str> {
ARGS.get_arg_flag_value(name)
}
pub fn rap_and_cargo_args() -> [&'static [String]; 2] {
[&ARGS.args_group1, &ARGS.args_group2]
}
pub fn is_current_compile_crate() -> bool {
ARGS.is_current_compile_crate()
}
pub fn filter_crate_type() -> bool {
if let Some(s) = get_arg_flag_value("--crate-type") {
return match s {
"proc-macro" => false,
"bin" if get_arg_flag_value("--crate-name") == Some("build_script_build") => false,
_ => true,
};
}
true
}
pub fn get_arg(pos: usize) -> Option<&'static str> {
ARGS.args.get(pos).map(|x| x.as_str())
}
pub fn skip2() -> &'static [String] {
ARGS.args.get(2..).unwrap_or(&[])
}
pub fn current_exe_path() -> &'static Path {
&ARGS.current_exe_path
}
pub fn timeout() -> Option<u64> {
ARGS.get_arg_flag_value("-timeout")?.parse().ok()
}