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 204 205 206 207 208
//!Collection of utilities related to types and their properties
#![no_std]
#![warn(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
use core::{mem, marker};
///Type information
#[repr(transparent)]
pub struct Type<T>(marker::PhantomData<T>);
impl<T> Type<T> {
///Returns object size
#[inline(always)]
pub const fn size() -> usize {
mem::size_of::<T>()
}
///Returns minimum alignment
#[inline(always)]
pub const fn align() -> usize {
mem::align_of::<T>()
}
#[inline(always)]
///Returns whether type is ZST
pub const fn is_zst() -> bool {
Self::size() == 0
}
#[inline(always)]
///Returns whether type has `Drop` implementation with side effects
pub const fn needs_drop() -> bool {
mem::needs_drop::<T>()
}
}
///Static assertion helper
///
///This assertion relies on the fact that generic code is always compiled when generic is actually
///used, hence on its own every constant within `Assert` would not produce compile error, even if
///you refer to concrete instance of `Assert`
///In order to perform assertion, you must use associated constant, otherwise generic constant is not evaluated.
#[repr(transparent)]
pub struct Assert<T>(marker::PhantomData<T>);
impl<T> Assert<T> {
///Asserts type requires no call `Drop::drop`
///
///This relies on `mem::needs_drop` which may or may not return correctly, but if it returns
///`false` then it guarantees `Drop` has no side effect. Hence this assert should be used when
///you need to make sure you generic type has no `Drop` side effect.
///
///## Usage
///
///```
///use type_traits::Assert;
///
///fn test<T>(input: T) {
/// let _ = Assert::<T>::NO_NEED_DROP;
///}
///
///test(0);
///```
pub const NO_NEED_DROP: () = assert!(!Type::<T>::needs_drop());
///Asserts type is not ZST.
///
///## Usage
///
///```
///use type_traits::Assert;
///
///fn test<T>(input: T) {
/// let _ = Assert::<T>::IS_NOT_ZST;
///}
///
///test(0);
///```
pub const IS_NOT_ZST: () = assert!(!Type::<T>::is_zst());
///Asserts type is ZST
///
///## Usage
///
///```
///use type_traits::Assert;
///
///fn test<T>(input: T) {
/// let _ = Assert::<T>::IS_ZST;
///}
///
///test(());
///```
pub const IS_ZST: () = assert!(Type::<T>::is_zst());
}
///Static assertion helper for pair of types
///
///This assertion relies on the fact that generic code is always compiled when generic is actually
///used, hence on its own every constant within `Assert` would not produce compile error, even if
///you refer to concrete instance of `Assert`
///In order to perform assertion, you must use associated constant, otherwise generic constant is not evaluated.
#[repr(transparent)]
pub struct Assert2<L, R>(marker::PhantomData<(L, R)>);
impl<L, R> Assert2<L, R> {
///Asserts both types are of the same size
///
///## Usage
///
///```
///use type_traits::Assert2;
///
///fn test<T, O>(input: T, default: O) -> O {
/// let _ = Assert2::<T, O>::IS_SAME_SIZE;
/// default
///}
///
///test(0u8, false);
///```
pub const IS_SAME_SIZE: () = assert!(Type::<L>::size() == Type::<R>::size());
///Asserts both types are of the minimum alignment.
///
///## Usage
///
///```
///use type_traits::Assert2;
///
///fn test<T, O>(input: T, default: O) -> O {
/// let _ = Assert2::<T, O>::IS_SAME_ALIGN;
/// default
///}
///
///test(0u8, false);
///```
pub const IS_SAME_ALIGN: () = assert!(Type::<L>::align() == Type::<R>::align());
///Asserts that `L` size is greater or equal to `R`
///
///## Usage
///
///```
///use type_traits::{Type, Assert2};
///
///fn test<T, O>(input: T, default: O) -> O {
/// assert!(Type::<T>::size() > Type::<O>::size());
/// let _ = Assert2::<T, O>::IS_LEFT_SIZE_GREATER_OR_EQUAL;
/// default
///}
///
///test(0u32, false);
///```
pub const IS_LEFT_SIZE_GREATER_OR_EQUAL: () = assert!(Type::<L>::size() >= Type::<R>::size());
///Asserts that `L` size is less that of `R`
///
///## Usage
///
///```
///use type_traits::{Type, Assert2};
///
///fn test<T, O>(input: T, default: O) -> O {
/// assert!(Type::<T>::size() < Type::<O>::size());
/// let _ = Assert2::<T, O>::IS_LEFT_SIZE_LESS;
/// default
///}
///
///test(false, 0u32);
///```
pub const IS_LEFT_SIZE_LESS: () = assert!(Type::<L>::size() < Type::<R>::size());
///Asserts that `L` minimum alignment is greater or equal to `R`
///
///## Usage
///
///```
///use type_traits::{Type, Assert2};
///
///fn test<T, O>(input: T, default: O) -> O {
/// assert!(Type::<T>::align() > Type::<O>::align());
/// let _ = Assert2::<T, O>::IS_LEFT_ALIGN_GREATER_OR_EQUAL;
/// default
///}
///
///test(0u32, false);
///```
pub const IS_LEFT_ALIGN_GREATER_OR_EQUAL: () = assert!(Type::<L>::align() >= Type::<R>::align());
///Asserts that `L` minimum alignment is less that of `R`
///
///## Usage
///
///```
///use type_traits::{Type, Assert2};
///
///fn test<T, O>(input: T, default: O) -> O {
/// assert!(Type::<T>::align() < Type::<O>::align());
/// let _ = Assert2::<T, O>::IS_LEFT_ALIGN_LESS;
/// default
///}
///
///test(0u8, 0u32);
///```
pub const IS_LEFT_ALIGN_LESS: () = assert!(Type::<L>::align() < Type::<R>::align());
}