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}