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. fmt(&self, f: &mut fmt::Formatter) -> fmt::Result15 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. span(&self) -> Option<Span>20 fn span(&self) -> Option<Span> { 21 None 22 } 23 } 24 25 impl<T: IdentFragment + ?Sized> IdentFragment for &T { span(&self) -> Option<Span>26 fn span(&self) -> Option<Span> { 27 <T as IdentFragment>::span(*self) 28 } 29 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result30 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 { span(&self) -> Option<Span>36 fn span(&self) -> Option<Span> { 37 <T as IdentFragment>::span(*self) 38 } 39 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 41 IdentFragment::fmt(*self, f) 42 } 43 } 44 45 impl IdentFragment for Ident { span(&self) -> Option<Span>46 fn span(&self) -> Option<Span> { 47 Some(self.span()) 48 } 49 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result50 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 60 impl<T> IdentFragment for Cow<'_, T> 61 where 62 T: IdentFragment + ToOwned + ?Sized, 63 { span(&self) -> Option<Span>64 fn span(&self) -> Option<Span> { 65 T::span(self) 66 } 67 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result68 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