type_traits/lib.rs
1//!Collection of utilities related to types and their properties
2
3#![no_std]
4#![warn(missing_docs)]
5#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
6
7use core::{mem, marker};
8
9///Type information
10#[repr(transparent)]
11pub struct Type<T>(marker::PhantomData<T>);
12
13impl<T> Type<T> {
14 ///Returns object size
15 #[inline(always)]
16 pub const fn size() -> usize {
17 mem::size_of::<T>()
18 }
19
20 ///Returns minimum alignment
21 #[inline(always)]
22 pub const fn align() -> usize {
23 mem::align_of::<T>()
24 }
25
26 #[inline(always)]
27 ///Returns whether type is ZST
28 pub const fn is_zst() -> bool {
29 Self::size() == 0
30 }
31
32 #[inline(always)]
33 ///Returns whether type has `Drop` implementation with side effects
34 pub const fn needs_drop() -> bool {
35 mem::needs_drop::<T>()
36 }
37}
38
39///Static assertion helper
40///
41///This assertion relies on the fact that generic code is always compiled when generic is actually
42///used, hence on its own every constant within `Assert` would not produce compile error, even if
43///you refer to concrete instance of `Assert`
44///In order to perform assertion, you must use associated constant, otherwise generic constant is not evaluated.
45#[repr(transparent)]
46pub struct Assert<T>(marker::PhantomData<T>);
47
48impl<T> Assert<T> {
49 ///Asserts type requires no call `Drop::drop`
50 ///
51 ///This relies on `mem::needs_drop` which may or may not return correctly, but if it returns
52 ///`false` then it guarantees `Drop` has no side effect. Hence this assert should be used when
53 ///you need to make sure you generic type has no `Drop` side effect.
54 ///
55 ///## Usage
56 ///
57 ///```
58 ///use type_traits::Assert;
59 ///
60 ///fn test<T>(input: T) {
61 /// let _ = Assert::<T>::NO_NEED_DROP;
62 ///}
63 ///
64 ///test(0);
65 ///```
66 pub const NO_NEED_DROP: () = assert!(!Type::<T>::needs_drop());
67
68 ///Asserts type is not ZST.
69 ///
70 ///## Usage
71 ///
72 ///```
73 ///use type_traits::Assert;
74 ///
75 ///fn test<T>(input: T) {
76 /// let _ = Assert::<T>::IS_NOT_ZST;
77 ///}
78 ///
79 ///test(0);
80 ///```
81 pub const IS_NOT_ZST: () = assert!(!Type::<T>::is_zst());
82
83 ///Asserts type is ZST
84 ///
85 ///## Usage
86 ///
87 ///```
88 ///use type_traits::Assert;
89 ///
90 ///fn test<T>(input: T) {
91 /// let _ = Assert::<T>::IS_ZST;
92 ///}
93 ///
94 ///test(());
95 ///```
96 pub const IS_ZST: () = assert!(Type::<T>::is_zst());
97}
98
99///Static assertion helper for pair of types
100///
101///This assertion relies on the fact that generic code is always compiled when generic is actually
102///used, hence on its own every constant within `Assert` would not produce compile error, even if
103///you refer to concrete instance of `Assert`
104///In order to perform assertion, you must use associated constant, otherwise generic constant is not evaluated.
105#[repr(transparent)]
106pub struct Assert2<L, R>(marker::PhantomData<(L, R)>);
107
108impl<L, R> Assert2<L, R> {
109 ///Asserts both types are of the same size
110 ///
111 ///## Usage
112 ///
113 ///```
114 ///use type_traits::Assert2;
115 ///
116 ///fn test<T, O>(input: T, default: O) -> O {
117 /// let _ = Assert2::<T, O>::IS_SAME_SIZE;
118 /// default
119 ///}
120 ///
121 ///test(0u8, false);
122 ///```
123 pub const IS_SAME_SIZE: () = assert!(Type::<L>::size() == Type::<R>::size());
124
125 ///Asserts both types are of the minimum alignment.
126 ///
127 ///## Usage
128 ///
129 ///```
130 ///use type_traits::Assert2;
131 ///
132 ///fn test<T, O>(input: T, default: O) -> O {
133 /// let _ = Assert2::<T, O>::IS_SAME_ALIGN;
134 /// default
135 ///}
136 ///
137 ///test(0u8, false);
138 ///```
139 pub const IS_SAME_ALIGN: () = assert!(Type::<L>::align() == Type::<R>::align());
140
141 ///Asserts that `L` size is greater or equal to `R`
142 ///
143 ///## Usage
144 ///
145 ///```
146 ///use type_traits::{Type, Assert2};
147 ///
148 ///fn test<T, O>(input: T, default: O) -> O {
149 /// assert!(Type::<T>::size() > Type::<O>::size());
150 /// let _ = Assert2::<T, O>::IS_LEFT_SIZE_GREATER_OR_EQUAL;
151 /// default
152 ///}
153 ///
154 ///test(0u32, false);
155 ///```
156 pub const IS_LEFT_SIZE_GREATER_OR_EQUAL: () = assert!(Type::<L>::size() >= Type::<R>::size());
157
158 ///Asserts that `L` size is less that of `R`
159 ///
160 ///## Usage
161 ///
162 ///```
163 ///use type_traits::{Type, Assert2};
164 ///
165 ///fn test<T, O>(input: T, default: O) -> O {
166 /// assert!(Type::<T>::size() < Type::<O>::size());
167 /// let _ = Assert2::<T, O>::IS_LEFT_SIZE_LESS;
168 /// default
169 ///}
170 ///
171 ///test(false, 0u32);
172 ///```
173 pub const IS_LEFT_SIZE_LESS: () = assert!(Type::<L>::size() < Type::<R>::size());
174
175 ///Asserts that `L` minimum alignment is greater or equal to `R`
176 ///
177 ///## Usage
178 ///
179 ///```
180 ///use type_traits::{Type, Assert2};
181 ///
182 ///fn test<T, O>(input: T, default: O) -> O {
183 /// assert!(Type::<T>::align() > Type::<O>::align());
184 /// let _ = Assert2::<T, O>::IS_LEFT_ALIGN_GREATER_OR_EQUAL;
185 /// default
186 ///}
187 ///
188 ///test(0u32, false);
189 ///```
190 pub const IS_LEFT_ALIGN_GREATER_OR_EQUAL: () = assert!(Type::<L>::align() >= Type::<R>::align());
191
192 ///Asserts that `L` minimum alignment is less that of `R`
193 ///
194 ///## Usage
195 ///
196 ///```
197 ///use type_traits::{Type, Assert2};
198 ///
199 ///fn test<T, O>(input: T, default: O) -> O {
200 /// assert!(Type::<T>::align() < Type::<O>::align());
201 /// let _ = Assert2::<T, O>::IS_LEFT_ALIGN_LESS;
202 /// default
203 ///}
204 ///
205 ///test(0u8, 0u32);
206 ///```
207 pub const IS_LEFT_ALIGN_LESS: () = assert!(Type::<L>::align() < Type::<R>::align());
208}