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
use std::ops::Deref;

use quote::ToTokens;

use crate::maybe_borrowed::MaybeBorrowed;

pub struct TokenCmpWrapper<T: ToTokens>(pub T);

impl<T> Deref for TokenCmpWrapper<T>
where
    T: ToTokens,
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T, U> PartialEq<TokenCmpWrapper<U>> for TokenCmpWrapper<T>
where
    T: ToTokens,
    U: ToTokens,
{
    fn eq(&self, other: &TokenCmpWrapper<U>) -> bool {
        self.0.to_token_stream().to_string() == other.0.to_token_stream().to_string()
    }
}

impl<T> Eq for TokenCmpWrapper<T> where T: ToTokens {}

impl<T> Ord for TokenCmpWrapper<T>
where
    T: ToTokens,
{
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.0
            .to_token_stream()
            .to_string()
            .cmp(&other.0.to_token_stream().to_string())
    }
}

impl<T> PartialOrd for TokenCmpWrapper<T>
where
    T: ToTokens,
{
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a, T, U> From<U> for TokenCmpWrapper<MaybeBorrowed<'a, T>>
where
    MaybeBorrowed<'a, T>: ToTokens,
    U: Into<MaybeBorrowed<'a, T>>,
{
    fn from(value: U) -> Self {
        TokenCmpWrapper(value.into())
    }
}

impl<'a, 'b, T> From<T> for MaybeBorrowed<'b, TokenCmpWrapper<MaybeBorrowed<'a, T>>>
where
    MaybeBorrowed<'a, T>: ToTokens,
{
    fn from(value: T) -> Self {
        MaybeBorrowed::Owned(TokenCmpWrapper(value.into()))
    }
}

impl<'a, T> From<&'a T> for MaybeBorrowed<'a, TokenCmpWrapper<MaybeBorrowed<'a, T>>>
where
    MaybeBorrowed<'a, T>: ToTokens,
{
    fn from(value: &'a T) -> Self {
        MaybeBorrowed::Owned(TokenCmpWrapper(value.into()))
    }
}

impl<T> ToTokens for TokenCmpWrapper<T>
where
    T: ToTokens,
{
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        (**self).to_tokens(tokens);
    }

    fn to_token_stream(&self) -> proc_macro2::TokenStream {
        (**self).to_token_stream()
    }

    fn into_token_stream(self) -> proc_macro2::TokenStream
    where
        Self: Sized,
    {
        self.to_token_stream()
    }
}