1 use proc_macro2::{Ident, Span}; 2 use std::borrow::Cow; 3 use std::fmt; 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 pub trait IdentFragment { 12 /// Format this value as an identifier fragment. fmt(&self, f: &mut fmt::Formatter) -> fmt::Result13 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. span(&self) -> Option<Span>18 fn span(&self) -> Option<Span> { 19 None 20 } 21 } 22 23 impl<T: IdentFragment + ?Sized> IdentFragment for &T { span(&self) -> Option<Span>24 fn span(&self) -> Option<Span> { 25 <T as IdentFragment>::span(*self) 26 } 27 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result28 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 29 IdentFragment::fmt(*self, f) 30 } 31 } 32 33 impl<T: IdentFragment + ?Sized> IdentFragment for &mut T { span(&self) -> Option<Span>34 fn span(&self) -> Option<Span> { 35 <T as IdentFragment>::span(*self) 36 } 37 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 39 IdentFragment::fmt(*self, f) 40 } 41 } 42 43 impl IdentFragment for Ident { span(&self) -> Option<Span>44 fn span(&self) -> Option<Span> { 45 Some(self.span()) 46 } 47 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result48 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 58 impl<T> IdentFragment for Cow<'_, T> 59 where 60 T: IdentFragment + ToOwned + ?Sized, 61 { span(&self) -> Option<Span>62 fn span(&self) -> Option<Span> { 63 T::span(self) 64 } 65 fmt(&self, f: &mut fmt::Formatter) -> fmt::Result66 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. 73 macro_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 85 ident_fragment_display!(bool, str, String, char); 86 ident_fragment_display!(u8, u16, u32, u64, u128, usize); 87