1#![doc = include_str!("../README.md")]
2#![forbid(unsafe_code)]
3#![deny(
4 clippy::all,
5 clippy::complexity,
6 clippy::expect_used,
7 clippy::indexing_slicing,
8 clippy::panic,
9 clippy::pedantic,
10 clippy::perf,
11 clippy::style,
12 clippy::suspicious,
13 clippy::todo,
14 clippy::unimplemented,
15 clippy::unwrap_used,
16 future_incompatible,
17 keyword_idents,
18 let_underscore,
19 missing_docs,
20 nonstandard_style,
21 refining_impl_trait,
22 rust_2018_compatibility,
23 rust_2018_idioms,
24 rust_2021_compatibility,
25 rust_2024_compatibility,
26 unreachable_pub,
27 unused
28)]
29#![warn(clippy::nursery)]
30use std::{
31 fmt,
32 ops::{Deref, DerefMut},
33};
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct CodePath(String);
38
39impl fmt::Display for CodePath {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "{}", self.0)
42 }
43}
44
45impl From<&str> for CodePath {
46 fn from(s: &str) -> Self {
47 Self(s.into())
48 }
49}
50
51impl From<String> for CodePath {
52 fn from(s: String) -> Self {
53 Self(s)
54 }
55}
56
57impl From<CodePath> for String {
58 fn from(val: CodePath) -> Self {
59 val.0
60 }
61}
62
63impl Deref for CodePath {
64 type Target = String;
65
66 fn deref(&self) -> &Self::Target {
67 &self.0
68 }
69}
70
71impl DerefMut for CodePath {
72 fn deref_mut(&mut self) -> &mut Self::Target {
73 &mut self.0
74 }
75}
76
77#[macro_export]
80macro_rules! code_path {
81 () => {
82 $crate::CodePath::from(format!(
83 "{}, {}",
84 $crate::code_scope!(),
85 $crate::code_loc!()
86 ))
87 };
88}
89
90#[macro_export]
92macro_rules! code_scope {
93 () => {{
94 const fn f() {}
95 fn type_name_of<T>(_: T) -> &'static str {
96 ::std::any::type_name::<T>()
97 }
98 type_name_of(f)
99 .strip_suffix("::f")
100 .unwrap_or_default()
101 .trim_end_matches("::{{closure}}")
102 }};
103}
104
105#[macro_export]
107macro_rules! code_loc {
108 () => {
109 concat!(file!(), ":", line!(), ":", column!())
110 };
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn nesting() {
119 fn foo() -> &'static str {
120 fn bar() -> &'static str {
121 code_scope!()
122 }
123 bar()
124 }
125
126 assert_eq!(foo(), "code_path::tests::nesting::foo::bar");
127 }
128
129 #[test]
130 fn ending_cloures() {
131 fn foo() -> &'static str {
132 #[allow(clippy::redundant_closure_call)]
133 (|| (|| code_scope!())())()
134 }
135 assert_eq!(foo(), "code_path::tests::ending_cloures::foo");
136 }
137}