quote/
ident_fragment.rs

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