quote/
ident_fragment.rs

1use alloc::borrow::{Cow, ToOwned};
2use alloc::string::{String, ToString};
3use core::fmt;
4use proc_macro2::{Ident, Span};
5
6/// Specialized formatting trait used by `format_ident!`.
7///
8/// [`Ident`] arguments formatted using this trait will have their `r#` prefix
9/// stripped, if present.
10///
11/// See [`format_ident!`] for more information.
12///
13/// [`format_ident!`]: crate::format_ident
14pub trait IdentFragment {
15    /// Format this value as an identifier fragment.
16    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
17
18    /// Span associated with this `IdentFragment`.
19    ///
20    /// If non-`None`, may be inherited by formatted identifiers.
21    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
74// Limited set of types which this is implemented for, as we want to avoid types
75// which will often include non-identifier characters in their `Display` impl.
76macro_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);