1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::collections::HashSet;
use std::fmt::Display;
use std::fs;
use std::hash::Hash;
use std::path::Path;
use anyhow::anyhow;
use pathdiff::diff_paths;
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)
}
}
pub trait PathExt {
fn file_name_str(&self) -> Option<&str>;
fn directory_name_str(&self) -> Option<&str>;
fn get_relative_path_to<P>(&self, path: P, exclude_file: bool) -> String
where
P: AsRef<Path>;
}
impl PathExt for std::path::Path {
#[inline]
fn file_name_str(&self) -> Option<&str> {
self.file_name().and_then(std::ffi::OsStr::to_str)
}
#[inline]
fn directory_name_str(&self) -> Option<&str> {
self.parent().and_then(|p| p.to_str())
}
#[inline]
fn get_relative_path_to<P>(&self, path: P, exclude_file: bool) -> String
where
P: AsRef<Path>,
{
if exclude_file {
let src = self.parent().and_then(|p| p.to_str()).unwrap();
diff_paths(path, src).unwrap().to_str().unwrap().to_owned()
} else {
diff_paths(path, self).unwrap().to_str().unwrap().to_owned()
}
}
}