1#[derive(Debug)]
3pub struct Location {
4 pub file: String,
5 pub line: u32,
6 pub column: u32,
7}
8
9#[allow(clippy::new_without_default)]
10impl Location {
11 #[track_caller]
12 pub fn new() -> Self {
13 location!()
14 }
15}
16
17impl core::fmt::Display for Location {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 write!(f, "{}:{}:{}", self.file, self.line, self.column)
20 }
21}
22
23#[macro_export]
25macro_rules! location {
26 () => {{
27 let caller = ::core::panic::Location::caller();
28 $crate::Location {
29 file: caller.file().to_string(),
30 line: caller.line(),
31 column: caller.column(),
32 }
33 }};
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn test_location() {
42 let file = file!();
43 let column = 24;
45 let line = line!();
46 let location = location!();
47 assert!(matches!(
48 location,
49 Location {
50 file: _,
51 line: _,
52 column: _
53 }
54 ));
55 assert_eq!(location.file, file);
56 assert_eq!(location.line, line + 1);
57 assert_eq!(location.column, column);
58
59 let column = 24;
60 let line = line!();
61 let location = Location::new();
62 assert!(matches!(
63 location,
64 Location {
65 file: _,
66 line: _,
67 column: _
68 }
69 ));
70 assert_eq!(location.file, file);
71 assert_eq!(location.line, line + 1);
72 assert_eq!(location.column, column);
73 }
74}