1use crate::syntax::{NamedType, Ty1, Type};
2use proc_macro2::{Ident, Span};
3use std::hash::{Hash, Hasher};
4use syn::Token;
5
6#[derive(Copy, Clone, PartialEq, Eq, Hash)]
7pub enum ImplKey<'a> {
8    RustBox(NamedImplKey<'a>),
9    RustVec(NamedImplKey<'a>),
10    UniquePtr(NamedImplKey<'a>),
11    SharedPtr(NamedImplKey<'a>),
12    WeakPtr(NamedImplKey<'a>),
13    CxxVector(NamedImplKey<'a>),
14}
15
16#[derive(Copy, Clone)]
17pub struct NamedImplKey<'a> {
18    pub begin_span: Span,
19    pub rust: &'a Ident,
20    pub lt_token: Option<Token![<]>,
21    pub gt_token: Option<Token![>]>,
22    pub end_span: Span,
23}
24
25impl Type {
26    pub(crate) fn impl_key(&self) -> Option<ImplKey> {
27        if let Type::RustBox(ty) = self {
28            if let Type::Ident(ident) = &ty.inner {
29                return Some(ImplKey::RustBox(NamedImplKey::new(ty, ident)));
30            }
31        } else if let Type::RustVec(ty) = self {
32            if let Type::Ident(ident) = &ty.inner {
33                return Some(ImplKey::RustVec(NamedImplKey::new(ty, ident)));
34            }
35        } else if let Type::UniquePtr(ty) = self {
36            if let Type::Ident(ident) = &ty.inner {
37                return Some(ImplKey::UniquePtr(NamedImplKey::new(ty, ident)));
38            }
39        } else if let Type::SharedPtr(ty) = self {
40            if let Type::Ident(ident) = &ty.inner {
41                return Some(ImplKey::SharedPtr(NamedImplKey::new(ty, ident)));
42            }
43        } else if let Type::WeakPtr(ty) = self {
44            if let Type::Ident(ident) = &ty.inner {
45                return Some(ImplKey::WeakPtr(NamedImplKey::new(ty, ident)));
46            }
47        } else if let Type::CxxVector(ty) = self {
48            if let Type::Ident(ident) = &ty.inner {
49                return Some(ImplKey::CxxVector(NamedImplKey::new(ty, ident)));
50            }
51        }
52        None
53    }
54}
55
56impl<'a> PartialEq for NamedImplKey<'a> {
57    fn eq(&self, other: &Self) -> bool {
58        PartialEq::eq(self.rust, other.rust)
59    }
60}
61
62impl<'a> Eq for NamedImplKey<'a> {}
63
64impl<'a> Hash for NamedImplKey<'a> {
65    fn hash<H: Hasher>(&self, hasher: &mut H) {
66        self.rust.hash(hasher);
67    }
68}
69
70impl<'a> NamedImplKey<'a> {
71    fn new(outer: &Ty1, inner: &'a NamedType) -> Self {
72        NamedImplKey {
73            begin_span: outer.name.span(),
74            rust: &inner.rust,
75            lt_token: inner.generics.lt_token,
76            gt_token: inner.generics.gt_token,
77            end_span: outer.rangle.span,
78        }
79    }
80}
81