1use std::path::Path;
4
5extern crate proc_macro;
6
7pub struct PrettySpan(pub proc_macro2::Span);
10impl std::fmt::Display for PrettySpan {
11 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12 if proc_macro::is_available() {
13 use std::path::MAIN_SEPARATOR;
14
15 let span = self.0.unwrap();
16
17 let path = span.file();
18 let path = make_source_path_relative(&path);
19 let mut path_str = path.display().to_string();
20 if '/' != MAIN_SEPARATOR && path.is_relative() {
21 path_str = path_str.replace(MAIN_SEPARATOR, "/");
23 }
24
25 write!(
26 f,
27 "{}:{}:{}",
28 path_str,
29 span.start().line(),
30 span.start().column(),
31 )?;
32 return Ok(());
33 }
34
35 write!(
36 f,
37 "unknown:{}:{}",
38 self.0.start().line,
39 self.0.start().column
40 )
41 }
42}
43
44pub struct PrettyRowCol(pub proc_macro2::Span);
46impl std::fmt::Display for PrettyRowCol {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 let span = self.0;
49 write!(f, "{}:{}", span.start().line, span.start().column)
50 }
51}
52
53pub fn make_source_path_relative(source_path: &impl AsRef<Path>) -> &Path {
55 let source_path = source_path.as_ref();
56 std::env::var_os("DFIR_BASE_DIR")
57 .and_then(|base_dir| source_path.strip_prefix(base_dir).ok())
58 .or_else(|| {
59 let manifest_dir = std::env::var_os("CARGO_MANIFEST_DIR")?;
60 source_path.strip_prefix(manifest_dir).ok()
61 })
62 .unwrap_or(source_path)
63}