use std::collections::HashSet;
use std::ffi::OsStr;
use std::fmt::Display;
use std::fs;
use std::hash::Hash;
use std::path::Path;
use anyhow::anyhow;
pub fn mod_from_rust_path(code_path: &str, crate_path: &str) -> String {
Path::new(code_path)
.strip_prefix(Path::new(crate_path).join("src"))
.unwrap()
.with_extension("")
.into_os_string()
.into_string()
.unwrap()
.replace('/', "::")
}
pub fn with_changed_file<F: FnOnce() -> anyhow::Result<()>>(
path: &str,
append_content: &str,
f: F,
) -> anyhow::Result<()> {
let content_original = fs::read_to_string(path)?;
fs::write(path, content_original.clone() + append_content)?;
f()?;
Ok(fs::write(path, content_original)?)
}
pub fn find_all_duplicates<T>(iter: &[T]) -> Vec<T>
where
T: Eq + Hash + Clone,
{
let mut uniq = HashSet::new();
iter.iter()
.filter(|x| !uniq.insert(*x))
.cloned()
.collect::<Vec<_>>()
}
pub fn get_symbols_if_no_duplicates(configs: &[crate::Opts]) -> Result<Vec<String>, anyhow::Error> {
let mut explicit_raw_symbols = Vec::new();
let mut all_symbols = Vec::new();
for config in configs {
let raw_ir_file = config.get_ir_file()?;
explicit_raw_symbols.extend(raw_ir_file.funcs.iter().map(|f| f.name.clone()));
all_symbols.extend(raw_ir_file.get_all_symbols(config));
}
let duplicates = find_all_duplicates(&explicit_raw_symbols);
if !duplicates.is_empty() {
let duplicated_symbols = duplicates.join(",");
let (symbol_str, verb_str) = if duplicates.len() == 1 {
("symbol", "has")
} else {
("symbols", "have")
};
return Err(anyhow!(
"{} [{}] {} already been defined",
symbol_str,
duplicated_symbols,
verb_str
));
}
Ok(all_symbols)
}
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub struct BlockIndex(pub usize);
impl BlockIndex {
pub const PRIMARY: BlockIndex = BlockIndex(0);
}
impl Display for BlockIndex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[extend::ext]
impl std::path::Path {
#[inline]
fn file_name_str(&self) -> Option<&str> {
self.file_name().and_then(OsStr::to_str)
}
}