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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//! This module defines a types to encode an IF test within the type system.
//!
//! The idea behind this concept is to match the condition, which is a type,
//! with the structure the test is implemented for.
//! This allows for a basic test similar to the following
//! ```rust
//! let result = std::any::TypeId::of::<i32>() == std::any::TypeId::of::<i32>();
//! if result {
//! // Condition matched
//! } else {
//! // Condition failed to match
//! }
//! ```
//!
//! # Example
//! ```rust,no_run
//! # extern crate ct_utils;
//! use ct_utils::prelude::*;
//!
//! // Trait to negate the signed-ness of a specific integer.
//! trait DeSignature<Target> {
//! type Result: ?Sized;
//! }
//!
//! impl<Target> DeSignature<Target> for i32 {
//! // Depending on Target, CTIf::Path will become signed or unsigned.
//! // Result will receive the type contained by CTIf::Path.
//! type Result = <IfCheck<i32> as CTIf<Target, u32, i32>>::Path;
//! }
//! ```
//!
//! # Notes
//! - If the receiving type parameter is constrained, the generic [`CTIf`] causes
//! compilation errors due to missing constraints.
//! You have to create your own specialized implementation of [`CTIf`], which is
//! made easy by utilizing the macro [`ctif_specialize`].
//!
use PhantomData;
/// Represents a boolean value encoded within the typesystem.
///
/// See also [`CTFalse`] and [`CTTrue`].
/// Generic version of an IF test encoded within the type system.
///
/// Condition is the type which must match.
/// OptionTrue will be passed into [`CTIf::Path`] if the condition match is TRUE.
/// OptionFalse will be passed into [`CTIf::Path`] if the condition match is FALSE.
///
/// Specialized versions of this trait are necessary when the receiving type parameter
/// is constrained. See [`ctif_specialize`] to create such a specialized version.
/// Type representing a FALSE value.
/// Type representing a TRUE value.
/// Actual type used to perform an IF check through the type system.
///
/// Performing an IF test through the type system requires both this structure as well
/// as the [`CTIf`] trait (or a specialized one). The typed that needs to be matched
/// is passed into this struct as generic argument for X.
/// The resulting type must then be cast as [`CTIf`] trait, which includes the desired type.
/// [`CTIf::Path`] will then hold the match relevant type.
/// eg
/// ```rust,ignore
/// <IfCheck<Subject> as CTIf<Desired, TypeTrue, TypeFalse>>::Path;
/// ```
/// Macro for specializing [`CTIf`].
///
/// If receiving associated types are constrained, the generic [`CTIf`] is not usable any more
/// because there is no syntax carrying over these constraints accross the IF test.
/// Solving this requires building a new trait similar to [`CTIf`] with constraints which are
/// specific to your use case. These constraints will be applied to [`CTIf::Path`].
///
/// This macro helps in building that specialization. It creates a specialized trait and implements
/// it for [`IfCheck`], the latter can be re-used accross specializations.
/// Implementers only need to provide a new name for the trait and the required constraints.
/// Provided outer attributes are applied to the newly created trait as well.
///
/// Using this specialized trait is analogue to using [`CTIf`] and [`IfCheck`].
///
/// # Example
/// ```rust,ignore
/// ctif_specialize {
/// /// Optional doc-attribute explaining things about the special IF test.
/// trait_name = "MySpecialIf",
/// conditions = [Add<u32>, Mul<u32>]
/// }
/// ```
///
/// That macro call will expand to the following code.
/// ```rust, ignore
/// /// Optional doc-attribute explaining things about the special IF test.
/// pub trait MySpecialIf<Condition, OptionTrue, OptionFalse> {
/// type Result: CTBool;
/// type Path: Add<u32> + Mul<u32>;
/// }
/// ```