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