1use crate::test_generator::Error;
2
3use crate::constants::*;
4use fehler::{throw, throws};
5use std::path::Path;
6use std::path::PathBuf;
7use tokio::fs;
8
9#[macro_export]
10macro_rules! construct_path {
11 ($root:expr, $($component:expr),*) => {
12 {
13 let mut path = $root.to_owned();
14 $(path = path.join($component);)*
15 path
16 }
17 };
18}
19#[macro_export]
20macro_rules! load_template {
21 ($file:expr) => {
22 include_str!(concat!(env!("CARGO_MANIFEST_DIR"), $file))
23 };
24}
25
26#[throws]
27pub async fn create_directory_all(path: &PathBuf) {
28 match path.exists() {
29 true => {}
30 false => {
31 fs::create_dir_all(path).await?;
32 }
33 };
34}
35
36#[throws]
37pub async fn create_file(root: &PathBuf, path: &PathBuf, content: &str) {
38 let file = path.strip_prefix(root)?.to_str().unwrap_or_default();
39
40 match path.exists() {
41 true => {
42 println!("{SKIP} [{file}] already exists")
43 }
44 false => {
45 fs::write(path, content).await?;
46 println!("{FINISH} [{file}] created");
47 }
48 };
49}
50
51#[throws]
52pub fn get_fuzz_id(fuzz_dir_path: &Path) -> i32 {
53 if fuzz_dir_path.exists() {
54 if fuzz_dir_path.read_dir()?.next().is_none() {
55 0
56 } else {
57 let entries = fuzz_dir_path.read_dir()?;
58 let mut max_num = -1;
59 for entry in entries {
60 let entry = entry?;
61 let file_name = entry.file_name().into_string().unwrap_or_default();
62 if file_name.starts_with("fuzz_") {
63 let stripped = file_name.strip_prefix("fuzz_").unwrap_or_default();
64 let num = stripped.parse::<i32>()?;
65 max_num = max_num.max(num);
66 }
67 }
68 max_num + 1
69 }
70 } else {
71 0
72 }
73}
74#[throws]
75pub async fn collect_program_packages(
76 program_name: Option<String>,
77) -> Vec<cargo_metadata::Package> {
78 let packages: Vec<cargo_metadata::Package> = program_packages(program_name).collect();
79 if packages.is_empty() {
80 throw!(Error::NoProgramsFound)
81 } else {
82 packages
83 }
84}
85pub fn program_packages(
86 program_name: Option<String>,
87) -> Box<dyn Iterator<Item = cargo_metadata::Package>> {
88 let cargo_toml_data = cargo_metadata::MetadataCommand::new()
89 .no_deps()
90 .exec()
91 .expect("Cargo.toml reading failed");
92
93 match program_name {
94 Some(name) => Box::new(
95 cargo_toml_data
96 .packages
97 .into_iter()
98 .filter(move |package| package.name == name),
99 ),
100 None => Box::new(cargo_toml_data.packages.into_iter().filter(|package| {
101 if let Some("programs") = package.manifest_path.iter().nth_back(2) {
103 return true;
104 }
105 false
106 })),
107 }
108}
109
110