use proc_macro2::{Ident, Span}; use std::borrow::Cow; use std::fmt; /// Specialized formatting trait used by `format_ident!`. /// /// [`Ident`] arguments formatted using this trait will have their `r#` prefix /// stripped, if present. /// /// See [`format_ident!`] for more information. pub trait IdentFragment { /// Format this value as an identifier fragment. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result; /// Span associated with this `IdentFragment`. /// /// If non-`None`, may be inherited by formatted identifiers. fn span(&self) -> Option { None } } impl IdentFragment for &T { fn span(&self) -> Option { ::span(*self) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { IdentFragment::fmt(*self, f) } } impl IdentFragment for &mut T { fn span(&self) -> Option { ::span(*self) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { IdentFragment::fmt(*self, f) } } impl IdentFragment for Ident { fn span(&self) -> Option { Some(self.span()) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let id = self.to_string(); if id.starts_with("r#") { fmt::Display::fmt(&id[2..], f) } else { fmt::Display::fmt(&id[..], f) } } } impl IdentFragment for Cow<'_, T> where T: IdentFragment + ToOwned + ?Sized, { fn span(&self) -> Option { T::span(self) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { T::fmt(self, f) } } // Limited set of types which this is implemented for, as we want to avoid types // which will often include non-identifier characters in their `Display` impl. macro_rules! ident_fragment_display { ($($T:ty),*) => { $( impl IdentFragment for $T { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) } } )* } } ident_fragment_display!(bool, str, String, char); ident_fragment_display!(u8, u16, u32, u64, u128, usize);