thiserror_impl/
unraw.rs

1use proc_macro2::{Ident, Span, TokenStream};
2use quote::ToTokens;
3use std::cmp::Ordering;
4use std::fmt::{self, Display};
5use std::hash::{Hash, Hasher};
6use syn::ext::IdentExt as _;
7use syn::parse::{Parse, ParseStream, Result};
8use syn::Index;
9
10#[derive(Clone)]
11#[repr(transparent)]
12pub struct IdentUnraw(Ident);
13
14impl IdentUnraw {
15    pub fn new(ident: Ident) -> Self {
16        IdentUnraw(ident)
17    }
18
19    pub fn to_local(&self) -> Ident {
20        let unraw = self.0.unraw();
21        let repr = unraw.to_string();
22        if syn::parse_str::<Ident>(&repr).is_err() {
23            if let "_" | "super" | "self" | "Self" | "crate" = repr.as_str() {
24                // Some identifiers are never allowed to appear as raw, like r#self and r#_.
25            } else {
26                return Ident::new_raw(&repr, Span::call_site());
27            }
28        }
29        unraw
30    }
31
32    pub fn set_span(&mut self, span: Span) {
33        self.0.set_span(span);
34    }
35}
36
37impl Display for IdentUnraw {
38    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
39        Display::fmt(&self.0.unraw(), formatter)
40    }
41}
42
43impl Eq for IdentUnraw {}
44
45impl PartialEq for IdentUnraw {
46    fn eq(&self, other: &Self) -> bool {
47        PartialEq::eq(&self.0.unraw(), &other.0.unraw())
48    }
49}
50
51impl PartialEq<str> for IdentUnraw {
52    fn eq(&self, other: &str) -> bool {
53        self.0 == other
54    }
55}
56
57impl Ord for IdentUnraw {
58    fn cmp(&self, other: &Self) -> Ordering {
59        Ord::cmp(&self.0.unraw(), &other.0.unraw())
60    }
61}
62
63impl PartialOrd for IdentUnraw {
64    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
65        Some(Self::cmp(self, other))
66    }
67}
68
69impl Parse for IdentUnraw {
70    fn parse(input: ParseStream) -> Result<Self> {
71        input.call(Ident::parse_any).map(IdentUnraw::new)
72    }
73}
74
75impl ToTokens for IdentUnraw {
76    fn to_tokens(&self, tokens: &mut TokenStream) {
77        self.0.unraw().to_tokens(tokens);
78    }
79}
80
81#[derive(Clone)]
82pub enum MemberUnraw {
83    Named(IdentUnraw),
84    Unnamed(Index),
85}
86
87impl MemberUnraw {
88    pub fn span(&self) -> Span {
89        match self {
90            MemberUnraw::Named(ident) => ident.0.span(),
91            MemberUnraw::Unnamed(index) => index.span,
92        }
93    }
94}
95
96impl Display for MemberUnraw {
97    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
98        match self {
99            MemberUnraw::Named(this) => Display::fmt(this, formatter),
100            MemberUnraw::Unnamed(this) => Display::fmt(&this.index, formatter),
101        }
102    }
103}
104
105impl Eq for MemberUnraw {}
106
107impl PartialEq for MemberUnraw {
108    fn eq(&self, other: &Self) -> bool {
109        match (self, other) {
110            (MemberUnraw::Named(this), MemberUnraw::Named(other)) => this == other,
111            (MemberUnraw::Unnamed(this), MemberUnraw::Unnamed(other)) => this == other,
112            _ => false,
113        }
114    }
115}
116
117impl PartialEq<str> for MemberUnraw {
118    fn eq(&self, other: &str) -> bool {
119        match self {
120            MemberUnraw::Named(this) => this == other,
121            MemberUnraw::Unnamed(_) => false,
122        }
123    }
124}
125
126impl Hash for MemberUnraw {
127    fn hash<H: Hasher>(&self, hasher: &mut H) {
128        match self {
129            MemberUnraw::Named(ident) => ident.0.unraw().hash(hasher),
130            MemberUnraw::Unnamed(index) => index.hash(hasher),
131        }
132    }
133}
134
135impl ToTokens for MemberUnraw {
136    fn to_tokens(&self, tokens: &mut TokenStream) {
137        match self {
138            MemberUnraw::Named(ident) => ident.to_local().to_tokens(tokens),
139            MemberUnraw::Unnamed(index) => index.to_tokens(tokens),
140        }
141    }
142}