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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
mod r#trait;
mod r#type;

use std::hash::Hash;
use std::ops::{Deref, DerefMut};

use better_any::{Tid, TidAble};
use quote::ToTokens;
pub use r#trait::Trait;
pub use r#type::Type;

use proc_macro2::TokenStream;

use crate::maybe_borrowed::MaybeBorrowed;

use super::{context::Context, passed_data::PassedData};

/// This indicates that some type can be turned into tokens that assert something.
/// Be aware that this only relies on rust's type checking, the code that is generated
/// is never actually meant to be executed. The generation functions in three distinct "Stages".
/// See below for more information on that.
///
///
/// The type implementing this must also be [`TidAble`], which is similar to [`Any`](std::any::Any)
/// but allows for non-'static lifetimes. The easiest way to implement it is to use the derive macro (`#[derive(Tid)]`)
///
/// # Idents
/// There is a need to ensure that there are no ident collisions among the generated code.
/// For that purpose in each stage there is a context provided, which contains some [`IdentGenerator`](crate::ident_generator::IdentGenerator).
/// Other than Idents passed into the methods by either `Self` or any parameters, use Idents generates by the `IdentGenerator`
/// exclusively to avoid any collisions.
///
/// # Generation "Stages"
/// ## Stage 1: Generatable
/// These tokens are generated for each type that implemets this trait once. This is the perfect place to put
/// tokens that are needed as "Setup" for any asserts.
/// ## Stage 2: Template
/// These tokens are generated for each unique instance of `Self`. You should put any tokens that should be unique
/// for each instance in here.
/// ## Stage 3: Assert
/// These tokens are generated for each unique Assert, which represent some type that is tested against `Self`.
/// No generation is actually happening until at least one assert is created for `Self`.
///
/// # Passed Data
/// There may be a need to pass data, for example generated idents, between stages. For that purpose
/// this trait provides a way to do so. See [`PassedData`](crate::passed_data::PassedData) for more information.
pub trait Generatable<'a, Assert>
where
    Self: TidAble<'a>,
    Assert: 'a + TidAble<'a>,
{
    /// The type of any data passed from the `Generatable` stage to proceeding stages.
    type GeneratableData: 'a;
    /// The type of any data passed from the `Template` stage to proceeding stages.
    type TemplateData: 'a;

    /// This is the method the `Generatable` stage is composed of. Should return Tokens (if any) generated by this stage,
    /// plus optionally any data passed to preceding stages.
    fn generatable(context: &mut Context) -> PassedData<Self::GeneratableData>
    where
        Self: Sized;

    /// This is the method the `Template` stage is composed of. Should return Tokens (if any) generated by this stage,
    /// plus optionally any data passed to preceding stages.
    fn template(
        &self,
        context: &mut Context,
        passed: &Self::GeneratableData,
    ) -> PassedData<Self::TemplateData>;

    /// This is the method the `Assert` stage is composed of. Should return Tokens generated by this stage.
    fn assert(
        &self,
        _context: &mut Context,
        _passed: (&Self::GeneratableData, &Self::TemplateData),
        _to_assert: &Assert,
    ) -> Option<TokenStream>;
}

#[derive(Tid)]
#[repr(transparent)]
pub struct StaticTid<T: 'static>(pub T);

impl<T: 'static> From<T> for StaticTid<T> {
    fn from(value: T) -> Self {
        Self(value)
    }
}

impl<'a, T> From<&'a T> for &'a StaticTid<T> {
    fn from(value: &'a T) -> Self {
        // Safe because StaticTid is #[repr(transparent)].
        unsafe { &*(value as *const T).cast::<StaticTid<T>>() }
    }
}

impl<'a, T> From<&'a mut T> for &'a mut StaticTid<T> {
    fn from(value: &'a mut T) -> Self {
        // Safe because StaticTid is #[repr(transparent)].
        unsafe { &mut *(value as *mut T).cast::<StaticTid<T>>() }
    }
}

impl<'a, U> From<&'a U> for MaybeBorrowed<'a, StaticTid<U>> {
    fn from(value: &'a U) -> Self {
        MaybeBorrowed::Borrowed(value.into())
    }
}

impl<'a, T> From<T> for MaybeBorrowed<'a, StaticTid<T>> {
    fn from(value: T) -> Self {
        MaybeBorrowed::Owned(StaticTid(value))
    }
}
impl<T: 'static> Deref for StaticTid<T> {
    type Target = T;

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

impl<T: 'static> DerefMut for StaticTid<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T: 'static + ToTokens> ToTokens for StaticTid<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

impl<T: 'static + PartialEq> PartialEq for StaticTid<T> {
    fn eq(&self, other: &Self) -> bool {
        (**self).eq(&**other)
    }
}

impl<T: 'static + Eq> Eq for StaticTid<T> {}

impl<T: 'static + PartialOrd> PartialOrd for StaticTid<T> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        (**self).partial_cmp(&**other)
    }
}

impl<T: 'static + Ord> Ord for StaticTid<T> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        (**self).cmp(&**other)
    }
}

impl<T: 'static + Hash> Hash for StaticTid<T> {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}