| 1 | use alloc::borrow::Cow; |
| 2 | use core::fmt; |
| 3 | use 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 |
| 13 | pub 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 | |
| 25 | impl<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 | |
| 35 | impl<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 | |
| 45 | impl 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: String = self.to_string(); |
| 52 | if let Some(id: &str) = id.strip_prefix("r#" ) { |
| 53 | fmt::Display::fmt(self:id, f) |
| 54 | } else { |
| 55 | fmt::Display::fmt(&id[..], f) |
| 56 | } |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | impl<T> IdentFragment for Cow<'_, T> |
| 61 | where |
| 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. |
| 75 | macro_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 | |
| 87 | ident_fragment_display!(bool, str, String, char); |
| 88 | ident_fragment_display!(u8, u16, u32, u64, u128, usize); |
| 89 | |