diff options
Diffstat (limited to 'third_party/rust/quote/src/ident_fragment.rs')
-rw-r--r-- | third_party/rust/quote/src/ident_fragment.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/third_party/rust/quote/src/ident_fragment.rs b/third_party/rust/quote/src/ident_fragment.rs new file mode 100644 index 0000000000..cf74024b48 --- /dev/null +++ b/third_party/rust/quote/src/ident_fragment.rs @@ -0,0 +1,86 @@ +use core::fmt; +use proc_macro2::{Ident, Span}; +use std::borrow::Cow; + +/// 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<Span> { + None + } +} + +impl<T: IdentFragment + ?Sized> IdentFragment for &T { + fn span(&self) -> Option<Span> { + <T as IdentFragment>::span(*self) + } + + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + IdentFragment::fmt(*self, f) + } +} + +impl<T: IdentFragment + ?Sized> IdentFragment for &mut T { + fn span(&self) -> Option<Span> { + <T as IdentFragment>::span(*self) + } + + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + IdentFragment::fmt(*self, f) + } +} + +impl IdentFragment for Ident { + fn span(&self) -> Option<Span> { + 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<T> IdentFragment for Cow<'_, T> +where + T: IdentFragment + ToOwned + ?Sized, +{ + fn span(&self) -> Option<Span> { + 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); |