blob: a83ce7475aaa64ce1dcb7cba29830452ff1e5649 [file] [log] [blame]
Adrian Taylorc8713432020-10-21 18:20:55 -07001use crate::syntax::{
2 Api, CppName, ExternFn, Impl, Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice,
3 Symbol, Ty1, Type, Types,
4};
5use proc_macro2::{Ident, Span};
David Tolnay6586c692020-10-03 23:48:19 -07006use std::borrow::Borrow;
David Tolnay7db73692019-10-20 14:51:12 -04007use std::hash::{Hash, Hasher};
David Tolnayc21b20a2020-03-15 23:25:32 -07008use std::mem;
David Tolnay9bfbea32020-04-22 18:12:43 -07009use std::ops::{Deref, DerefMut};
Adrian Taylorc8713432020-10-21 18:20:55 -070010use syn::Token;
David Tolnay16448732020-03-18 12:39:36 -070011
12impl Deref for ExternFn {
13 type Target = Signature;
14
15 fn deref(&self) -> &Self::Target {
16 &self.sig
17 }
18}
David Tolnayc21b20a2020-03-15 23:25:32 -070019
David Tolnay9bfbea32020-04-22 18:12:43 -070020impl DerefMut for ExternFn {
21 fn deref_mut(&mut self) -> &mut Self::Target {
22 &mut self.sig
23 }
24}
25
David Tolnayc21b20a2020-03-15 23:25:32 -070026impl Hash for Type {
27 fn hash<H: Hasher>(&self, state: &mut H) {
28 mem::discriminant(self).hash(state);
29 match self {
30 Type::Ident(t) => t.hash(state),
31 Type::RustBox(t) => t.hash(state),
32 Type::UniquePtr(t) => t.hash(state),
33 Type::Ref(t) => t.hash(state),
34 Type::Str(t) => t.hash(state),
Myron Ahneba35cf2020-02-05 19:41:51 +070035 Type::RustVec(t) => t.hash(state),
David Tolnay4377a9e2020-04-24 15:20:26 -070036 Type::CxxVector(t) => t.hash(state),
David Tolnay417305a2020-03-18 13:54:00 -070037 Type::Fn(t) => t.hash(state),
Adrian Taylorf5dd5522020-04-13 16:50:14 -070038 Type::Slice(t) => t.hash(state),
39 Type::SliceRefU8(t) => t.hash(state),
David Tolnayc21b20a2020-03-15 23:25:32 -070040 Type::Void(_) => {}
41 }
42 }
43}
44
45impl Eq for Type {}
46
47impl PartialEq for Type {
48 fn eq(&self, other: &Type) -> bool {
49 match (self, other) {
50 (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
51 (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
52 (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
53 (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
54 (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
Myron Ahneba35cf2020-02-05 19:41:51 +070055 (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
David Tolnay4377a9e2020-04-24 15:20:26 -070056 (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
David Tolnay417305a2020-03-18 13:54:00 -070057 (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
Adrian Taylorf5dd5522020-04-13 16:50:14 -070058 (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
59 (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
David Tolnayc21b20a2020-03-15 23:25:32 -070060 (Type::Void(_), Type::Void(_)) => true,
61 (_, _) => false,
62 }
63 }
64}
David Tolnay7db73692019-10-20 14:51:12 -040065
66impl Eq for Ty1 {}
67
68impl PartialEq for Ty1 {
69 fn eq(&self, other: &Ty1) -> bool {
David Tolnay35c82eb2020-03-18 16:48:28 -070070 let Ty1 {
71 name,
72 langle: _,
73 inner,
74 rangle: _,
75 } = self;
76 let Ty1 {
77 name: name2,
78 langle: _,
79 inner: inner2,
80 rangle: _,
81 } = other;
82 name == name2 && inner == inner2
David Tolnay7db73692019-10-20 14:51:12 -040083 }
84}
85
86impl Hash for Ty1 {
87 fn hash<H: Hasher>(&self, state: &mut H) {
David Tolnay35c82eb2020-03-18 16:48:28 -070088 let Ty1 {
89 name,
90 langle: _,
91 inner,
92 rangle: _,
93 } = self;
94 name.hash(state);
95 inner.hash(state);
David Tolnay7db73692019-10-20 14:51:12 -040096 }
97}
98
99impl Eq for Ref {}
100
101impl PartialEq for Ref {
102 fn eq(&self, other: &Ref) -> bool {
David Tolnay35c82eb2020-03-18 16:48:28 -0700103 let Ref {
104 ampersand: _,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700105 lifetime,
David Tolnay35c82eb2020-03-18 16:48:28 -0700106 mutability,
107 inner,
108 } = self;
109 let Ref {
110 ampersand: _,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700111 lifetime: lifetime2,
David Tolnay35c82eb2020-03-18 16:48:28 -0700112 mutability: mutability2,
113 inner: inner2,
114 } = other;
David Tolnay0bd50fa2020-04-22 15:31:33 -0700115 lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && inner == inner2
David Tolnay7db73692019-10-20 14:51:12 -0400116 }
117}
118
119impl Hash for Ref {
120 fn hash<H: Hasher>(&self, state: &mut H) {
David Tolnay35c82eb2020-03-18 16:48:28 -0700121 let Ref {
122 ampersand: _,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700123 lifetime,
David Tolnay35c82eb2020-03-18 16:48:28 -0700124 mutability,
125 inner,
126 } = self;
David Tolnay0bd50fa2020-04-22 15:31:33 -0700127 lifetime.hash(state);
David Tolnay35c82eb2020-03-18 16:48:28 -0700128 mutability.is_some().hash(state);
129 inner.hash(state);
David Tolnay7db73692019-10-20 14:51:12 -0400130 }
131}
David Tolnay417305a2020-03-18 13:54:00 -0700132
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700133impl Eq for Slice {}
134
135impl PartialEq for Slice {
136 fn eq(&self, other: &Slice) -> bool {
David Tolnayeb952ba2020-04-14 15:02:24 -0700137 let Slice { bracket: _, inner } = self;
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700138 let Slice {
139 bracket: _,
140 inner: inner2,
141 } = other;
142 inner == inner2
143 }
144}
145
146impl Hash for Slice {
147 fn hash<H: Hasher>(&self, state: &mut H) {
David Tolnayeb952ba2020-04-14 15:02:24 -0700148 let Slice { bracket: _, inner } = self;
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700149 inner.hash(state);
150 }
151}
152
David Tolnay417305a2020-03-18 13:54:00 -0700153impl Eq for Signature {}
154
155impl PartialEq for Signature {
156 fn eq(&self, other: &Signature) -> bool {
157 let Signature {
David Tolnaybdb576c2020-09-06 23:45:55 -0700158 unsafety,
David Tolnay417305a2020-03-18 13:54:00 -0700159 fn_token: _,
160 receiver,
161 args,
162 ret,
163 throws,
David Tolnaye3a48152020-04-08 19:38:05 -0700164 paren_token: _,
165 throws_tokens: _,
David Tolnay417305a2020-03-18 13:54:00 -0700166 } = self;
167 let Signature {
David Tolnaybdb576c2020-09-06 23:45:55 -0700168 unsafety: unsafety2,
David Tolnay417305a2020-03-18 13:54:00 -0700169 fn_token: _,
170 receiver: receiver2,
171 args: args2,
172 ret: ret2,
173 throws: throws2,
David Tolnaye3a48152020-04-08 19:38:05 -0700174 paren_token: _,
175 throws_tokens: _,
David Tolnay417305a2020-03-18 13:54:00 -0700176 } = other;
David Tolnaybdb576c2020-09-06 23:45:55 -0700177 unsafety.is_some() == unsafety2.is_some()
178 && receiver == receiver2
David Tolnaye3a48152020-04-08 19:38:05 -0700179 && ret == ret2
180 && throws == throws2
181 && args.len() == args2.len()
182 && args.iter().zip(args2).all(|(arg, arg2)| arg == arg2)
David Tolnay417305a2020-03-18 13:54:00 -0700183 }
184}
185
186impl Hash for Signature {
187 fn hash<H: Hasher>(&self, state: &mut H) {
188 let Signature {
David Tolnaybdb576c2020-09-06 23:45:55 -0700189 unsafety,
David Tolnay417305a2020-03-18 13:54:00 -0700190 fn_token: _,
191 receiver,
192 args,
193 ret,
194 throws,
David Tolnaye3a48152020-04-08 19:38:05 -0700195 paren_token: _,
196 throws_tokens: _,
David Tolnay417305a2020-03-18 13:54:00 -0700197 } = self;
David Tolnaybdb576c2020-09-06 23:45:55 -0700198 unsafety.is_some().hash(state);
David Tolnay417305a2020-03-18 13:54:00 -0700199 receiver.hash(state);
David Tolnaye3a48152020-04-08 19:38:05 -0700200 for arg in args {
201 arg.hash(state);
202 }
David Tolnay417305a2020-03-18 13:54:00 -0700203 ret.hash(state);
204 throws.hash(state);
205 }
206}
207
208impl Eq for Receiver {}
209
210impl PartialEq for Receiver {
211 fn eq(&self, other: &Receiver) -> bool {
David Tolnay417305a2020-03-18 13:54:00 -0700212 let Receiver {
David Tolnayfb6e3862020-04-20 01:33:23 -0700213 ampersand: _,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700214 lifetime,
David Tolnayfb6e3862020-04-20 01:33:23 -0700215 mutability,
David Tolnay05e11cc2020-04-20 02:13:56 -0700216 var: _,
217 ty,
David Tolnay62d360c2020-04-22 16:26:21 -0700218 shorthand: _,
David Tolnayfb6e3862020-04-20 01:33:23 -0700219 } = self;
220 let Receiver {
221 ampersand: _,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700222 lifetime: lifetime2,
David Tolnay417305a2020-03-18 13:54:00 -0700223 mutability: mutability2,
David Tolnay05e11cc2020-04-20 02:13:56 -0700224 var: _,
225 ty: ty2,
David Tolnay62d360c2020-04-22 16:26:21 -0700226 shorthand: _,
David Tolnay417305a2020-03-18 13:54:00 -0700227 } = other;
David Tolnay0bd50fa2020-04-22 15:31:33 -0700228 lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && ty == ty2
David Tolnay417305a2020-03-18 13:54:00 -0700229 }
230}
231
232impl Hash for Receiver {
233 fn hash<H: Hasher>(&self, state: &mut H) {
David Tolnayfb6e3862020-04-20 01:33:23 -0700234 let Receiver {
235 ampersand: _,
David Tolnay0bd50fa2020-04-22 15:31:33 -0700236 lifetime,
David Tolnayfb6e3862020-04-20 01:33:23 -0700237 mutability,
David Tolnay05e11cc2020-04-20 02:13:56 -0700238 var: _,
239 ty,
David Tolnay62d360c2020-04-22 16:26:21 -0700240 shorthand: _,
David Tolnayfb6e3862020-04-20 01:33:23 -0700241 } = self;
David Tolnay0bd50fa2020-04-22 15:31:33 -0700242 lifetime.hash(state);
David Tolnay417305a2020-03-18 13:54:00 -0700243 mutability.is_some().hash(state);
David Tolnay05e11cc2020-04-20 02:13:56 -0700244 ty.hash(state);
David Tolnay417305a2020-03-18 13:54:00 -0700245 }
246}
David Tolnay6586c692020-10-03 23:48:19 -0700247
248impl Hash for Impl {
249 fn hash<H: Hasher>(&self, state: &mut H) {
250 let Impl {
251 impl_token: _,
252 ty,
253 brace_token: _,
254 } = self;
255 ty.hash(state);
256 }
257}
258
259impl Eq for Impl {}
260
261impl PartialEq for Impl {
262 fn eq(&self, other: &Impl) -> bool {
263 let Impl {
264 impl_token: _,
265 ty,
266 brace_token: _,
267 } = self;
268 let Impl {
269 impl_token: _,
270 ty: ty2,
271 brace_token: _,
272 } = other;
273 ty == ty2
274 }
275}
276
277impl Borrow<Type> for &Impl {
278 fn borrow(&self) -> &Type {
279 &self.ty
280 }
281}
Adrian Taylorc8713432020-10-21 18:20:55 -0700282
283impl Pair {
284 /// Use this constructor when the item can't have a different
285 /// name in Rust and C++. For cases where #[rust_name] and similar
286 /// attributes can be used, construct the object by hand.
287 pub fn new(ns: Namespace, ident: Ident) -> Self {
288 Self {
289 rust: ident.clone(),
290 cxx: CppName::new(ns, ident),
291 }
292 }
293}
294
295impl ResolvableName {
296 pub fn new(ident: Ident) -> Self {
297 Self { rust: ident }
298 }
299
300 pub fn from_pair(pair: Pair) -> Self {
301 Self { rust: pair.rust }
302 }
303
304 pub fn make_self(span: Span) -> Self {
305 Self {
306 rust: Token![Self](span).into(),
307 }
308 }
309
310 pub fn is_self(&self) -> bool {
311 self.rust == "Self"
312 }
313
314 pub fn span(&self) -> Span {
315 self.rust.span()
316 }
317
318 pub fn to_symbol(&self, types: &Types) -> Symbol {
319 types.resolve(self).to_symbol()
320 }
321}
322
323impl Api {
324 pub fn get_namespace(&self) -> Option<&Namespace> {
325 match self {
326 Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
327 Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
328 Api::Enum(enm) => Some(&enm.ident.cxx.ns),
329 Api::Struct(strct) => Some(&strct.ident.cxx.ns),
330 Api::RustType(rty) => Some(&rty.ident.cxx.ns),
331 Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
332 Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
333 }
334 }
335}
336
337impl CppName {
338 pub fn new(ns: Namespace, ident: Ident) -> Self {
339 Self { ns, ident }
340 }
341
342 fn iter_all_segments(
343 &self,
344 ) -> std::iter::Chain<std::slice::Iter<Ident>, std::iter::Once<&Ident>> {
345 self.ns.iter().chain(std::iter::once(&self.ident))
346 }
347
348 fn join(&self, sep: &str) -> String {
349 self.iter_all_segments()
350 .map(|s| s.to_string())
351 .collect::<Vec<_>>()
352 .join(sep)
353 }
354
355 pub fn to_symbol(&self) -> Symbol {
356 Symbol::from_idents(self.iter_all_segments())
357 }
358
359 pub fn to_fully_qualified(&self) -> String {
360 format!("::{}", self.join("::"))
361 }
362}