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
mod r#trait;
mod r#type;

use better_any::TidAble;
pub use r#trait::Trait;
pub use r#type::Type;

use proc_macro2::TokenStream;

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>
where
    Self: 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;
    /// The type with can be checked against this template.
    type Assert: '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: &Self::Assert,
    ) -> Option<TokenStream>;
}