thiserror_impl/
unraw.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use proc_macro2::{Ident, Span, TokenStream};
use quote::ToTokens;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::hash::{Hash, Hasher};
use syn::ext::IdentExt as _;
use syn::parse::{Parse, ParseStream, Result};
use syn::Index;

#[derive(Clone)]
#[repr(transparent)]
pub struct IdentUnraw(Ident);

impl IdentUnraw {
    pub fn new(ident: Ident) -> Self {
        IdentUnraw(ident)
    }

    pub fn to_local(&self) -> Ident {
        let unraw = self.0.unraw();
        let repr = unraw.to_string();
        if syn::parse_str::<Ident>(&repr).is_err() {
            if let "_" | "super" | "self" | "Self" | "crate" = repr.as_str() {
                // Some identifiers are never allowed to appear as raw, like r#self and r#_.
            } else {
                return Ident::new_raw(&repr, Span::call_site());
            }
        }
        unraw
    }
}

impl Display for IdentUnraw {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0.unraw(), formatter)
    }
}

impl Eq for IdentUnraw {}

impl PartialEq for IdentUnraw {
    fn eq(&self, other: &Self) -> bool {
        PartialEq::eq(&self.0.unraw(), &other.0.unraw())
    }
}

impl PartialEq<str> for IdentUnraw {
    fn eq(&self, other: &str) -> bool {
        self.0 == other
    }
}

impl Ord for IdentUnraw {
    fn cmp(&self, other: &Self) -> Ordering {
        Ord::cmp(&self.0.unraw(), &other.0.unraw())
    }
}

impl PartialOrd for IdentUnraw {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(Self::cmp(self, other))
    }
}

impl Parse for IdentUnraw {
    fn parse(input: ParseStream) -> Result<Self> {
        input.call(Ident::parse_any).map(IdentUnraw::new)
    }
}

impl ToTokens for IdentUnraw {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.0.unraw().to_tokens(tokens);
    }
}

#[derive(Clone)]
pub enum MemberUnraw {
    Named(IdentUnraw),
    Unnamed(Index),
}

impl MemberUnraw {
    pub fn span(&self) -> Span {
        match self {
            MemberUnraw::Named(ident) => ident.0.span(),
            MemberUnraw::Unnamed(index) => index.span,
        }
    }
}

impl Eq for MemberUnraw {}

impl PartialEq for MemberUnraw {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (MemberUnraw::Named(this), MemberUnraw::Named(other)) => this == other,
            (MemberUnraw::Unnamed(this), MemberUnraw::Unnamed(other)) => this == other,
            _ => false,
        }
    }
}

impl PartialEq<str> for MemberUnraw {
    fn eq(&self, other: &str) -> bool {
        match self {
            MemberUnraw::Named(this) => this == other,
            MemberUnraw::Unnamed(_) => false,
        }
    }
}

impl Hash for MemberUnraw {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        match self {
            MemberUnraw::Named(ident) => ident.0.unraw().hash(hasher),
            MemberUnraw::Unnamed(index) => index.hash(hasher),
        }
    }
}

impl ToTokens for MemberUnraw {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            MemberUnraw::Named(ident) => ident.to_local().to_tokens(tokens),
            MemberUnraw::Unnamed(index) => index.to_tokens(tokens),
        }
    }
}