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