1use alloc::borrow::{Cow, ToOwned};
2use alloc::string::{String, ToString};
3use core::fmt;
4use proc_macro2::{Ident, Span};
5
6pub trait IdentFragment {
15 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
17
18 fn span(&self) -> Option<Span> {
22 None
23 }
24}
25
26impl<T: IdentFragment + ?Sized> IdentFragment for &T {
27 fn span(&self) -> Option<Span> {
28 <T as IdentFragment>::span(*self)
29 }
30
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 IdentFragment::fmt(*self, f)
33 }
34}
35
36impl<T: IdentFragment + ?Sized> IdentFragment for &mut T {
37 fn span(&self) -> Option<Span> {
38 <T as IdentFragment>::span(*self)
39 }
40
41 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 IdentFragment::fmt(*self, f)
43 }
44}
45
46impl IdentFragment for Ident {
47 fn span(&self) -> Option<Span> {
48 Some(self.span())
49 }
50
51 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52 let id = self.to_string();
53 if let Some(id) = id.strip_prefix("r#") {
54 fmt::Display::fmt(id, f)
55 } else {
56 fmt::Display::fmt(&id[..], f)
57 }
58 }
59}
60
61impl<T> IdentFragment for Cow<'_, T>
62where
63 T: IdentFragment + ToOwned + ?Sized,
64{
65 fn span(&self) -> Option<Span> {
66 T::span(self)
67 }
68
69 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70 T::fmt(self, f)
71 }
72}
73
74macro_rules! ident_fragment_display {
77 ($($T:ty),*) => {
78 $(
79 impl IdentFragment for $T {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 fmt::Display::fmt(self, f)
82 }
83 }
84 )*
85 };
86}
87
88ident_fragment_display!(bool, str, String, char);
89ident_fragment_display!(u8, u16, u32, u64, u128, usize);