quote/
ident_fragment.rs

1use alloc::borrow::Cow;
2use core::fmt;
3use proc_macro2::{Ident, Span};
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.
11///
12/// [`format_ident!`]: crate::format_ident
13pub trait IdentFragment {
14    /// Format this value as an identifier fragment.
15    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
16
17    /// Span associated with this `IdentFragment`.
18    ///
19    /// If non-`None`, may be inherited by formatted identifiers.
20    fn span(&self) -> Option<Span> {
21        None
22    }
23}
24
25impl<T: IdentFragment + ?Sized> IdentFragment for &T {
26    fn span(&self) -> Option<Span> {
27        <T as IdentFragment>::span(*self)
28    }
29
30    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31        IdentFragment::fmt(*self, f)
32    }
33}
34
35impl<T: IdentFragment + ?Sized> IdentFragment for &mut T {
36    fn span(&self) -> Option<Span> {
37        <T as IdentFragment>::span(*self)
38    }
39
40    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41        IdentFragment::fmt(*self, f)
42    }
43}
44
45impl IdentFragment for Ident {
46    fn span(&self) -> Option<Span> {
47        Some(self.span())
48    }
49
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        let id = self.to_string();
52        if let Some(id) = id.strip_prefix("r#") {
53            fmt::Display::fmt(id, f)
54        } else {
55            fmt::Display::fmt(&id[..], f)
56        }
57    }
58}
59
60impl<T> IdentFragment for Cow<'_, T>
61where
62    T: IdentFragment + ToOwned + ?Sized,
63{
64    fn span(&self) -> Option<Span> {
65        T::span(self)
66    }
67
68    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69        T::fmt(self, f)
70    }
71}
72
73// Limited set of types which this is implemented for, as we want to avoid types
74// which will often include non-identifier characters in their `Display` impl.
75macro_rules! ident_fragment_display {
76    ($($T:ty),*) => {
77        $(
78            impl IdentFragment for $T {
79                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80                    fmt::Display::fmt(self, f)
81                }
82            }
83        )*
84    };
85}
86
87ident_fragment_display!(bool, str, String, char);
88ident_fragment_display!(u8, u16, u32, u64, u128, usize);