core_extensions/type_level_bool.rs
1//! Type level booleans
2//!
3//! # Example
4//!
5//! Access of privileges based on renamed Boolean types.
6//!
7#![cfg_attr(feature = "phantom", doc = " ```rust")]
8#![cfg_attr(not(feature = "phantom"), doc = " ```ignore")]
9//! use std::mem;
10//! use std::marker::PhantomData;
11//!
12//! use core_extensions::CovariantPhantom;
13//!
14//! pub use core_extensions::type_level_bool::{
15//! Boolean as PrivilegeLevel,
16//! False as Unprivileged,
17//! True as Privileged,
18//! };
19//!
20//!
21//! #[repr(C)]
22//! #[derive(Debug)]
23//! struct User<P>{
24//! name: String,
25//! privilege_level: CovariantPhantom<P>,
26//! }
27//!
28//! impl<P: PrivilegeLevel> User<P>{
29//! fn new(name: String, privilege_level: P) -> Self {
30//! Self{name, privilege_level: PhantomData}
31//! }
32//! fn name(&self)->&str{
33//! &self.name
34//! }
35//! fn into_unprivileged(self) -> User<Unprivileged> {
36//! User{name: self.name, privilege_level: PhantomData}
37//! }
38//! fn as_unprivileged(self: &mut User<P>) -> &mut User<Unprivileged> {
39//! // Only the type parameter P changes here
40//! unsafe{ mem::transmute(self) }
41//! }
42//! }
43//!
44//! impl User<Privileged>{
45//! fn set_name(&mut self, name: String){
46//! self.name = name;
47//! }
48//! }
49//!
50//! let mut user: User<Privileged> = User::new("bob".into(), Privileged);
51//! assert_eq!(user.name(), "bob");
52//!
53//! user.set_name("paul".into());
54//! assert_eq!(user.name(), "paul");
55//!
56//! {
57//! let user: &mut User<Unprivileged> = user.as_unprivileged();
58//!
59//! // Unprivileged Users can't change their name.
60//! // user.set_name("james".into());
61//!
62//! assert_eq!(user.name(), "paul");
63//! }
64//!
65//! user.set_name("john".into());
66//! assert_eq!(user.name(), "john");
67//!
68//! ```
69//!
70//!
71
72#[cfg(feature = "const_default")]
73use crate::ConstDefault;
74
75#[cfg(not(feature = "const_default"))]
76use std_::marker::Sized as ConstDefault;
77
78
79
80use std_::fmt::{self, Debug, Display};
81use std_::ops;
82
83#[cfg(feature = "marker_type")]
84use crate::MarkerType;
85
86#[cfg(not(feature = "marker_type"))]
87use std_::marker::Sized as MarkerType;
88
89
90/// Represents a type-level `true`
91#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
92pub struct True;
93
94/// Represents a type-level `false`
95#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
96pub struct False;
97
98impl Display for True {
99 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100 f.write_str("True")
101 }
102}
103
104impl Display for False {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 f.write_str("False")
107 }
108}
109
110mod sealed {
111 use super::{False, True};
112 pub trait Sealed {}
113 impl Sealed for True {}
114 impl Sealed for False {}
115}
116use self::sealed::Sealed;
117
118#[cfg(feature = "marker_type")]
119unsafe impl MarkerType for True {}
120
121#[cfg(feature = "marker_type")]
122unsafe impl MarkerType for False {}
123
124const _: &[[(); 0]] = &[
125 [(); std_::mem::size_of::<True>()],
126 [(); std_::mem::size_of::<False>()],
127 [(); std_::mem::align_of::<True>() - 1],
128 [(); std_::mem::align_of::<False>() - 1],
129];
130
131#[cfg(feature = "const_default")]
132impl ConstDefault for True {
133 const DEFAULT: Self = True;
134}
135
136#[cfg(feature = "const_default")]
137impl ConstDefault for False {
138 const DEFAULT: Self = False;
139}
140
141/// Represents a type-level `bool`
142///
143/// Only implemented on [`True`] and [`False`].
144///
145/// For examples look at [the module-level documentation](./index.html).
146///
147/// This trait is sealed and cannot be implemented for types outside this crate.
148///
149/// [`True`]: ./struct.True.html
150/// [`False`]: ./struct.False.html
151pub trait Boolean:
152 Sealed
153 + MarkerType
154 + ConstDefault
155 + Default
156 + Sized
157 + Debug
158 + Copy
159 + Clone
160 + ops::Not
161 + ops::BitAnd<True, Output = Self>
162 + ops::BitAnd<False, Output = False>
163 + ops::BitAnd<Self, Output = Self>
164 + ops::BitOr<True, Output = True>
165 + ops::BitOr<False, Output = Self>
166 + ops::BitOr<Self, Output = Self>
167 + ops::BitXor<True, Output = <Self as ops::Not>::Output>
168 + ops::BitXor<False, Output = Self>
169 + ops::BitXor<Self, Output = False>
170{
171 /// The `bool` value of this type
172 const VALUE: bool;
173}
174
175impl Boolean for True {
176 const VALUE: bool = true;
177}
178impl Boolean for False {
179 const VALUE: bool = false;
180}
181
182mod internals {
183 #[cfg(feature = "const_default")]
184 use crate::ConstDefault;
185
186 use super::{Boolean, False, True, Not};
187
188 use std_::ops;
189
190 impl ops::Not for True {
191 type Output = False;
192 fn not(self) -> Self::Output {
193 False
194 }
195 }
196 impl ops::Not for False {
197 type Output = True;
198 fn not(self) -> Self::Output {
199 True
200 }
201 }
202
203 impl<B> ops::BitAnd<B> for False {
204 type Output = False;
205 fn bitand(self, _: B) -> Self::Output {
206 False
207 }
208 }
209 impl<B> ops::BitAnd<B> for True {
210 type Output = B;
211 fn bitand(self, v: B) -> Self::Output {
212 v
213 }
214 }
215
216 impl<B> ops::BitOr<B> for True {
217 type Output = True;
218 fn bitor(self, _: B) -> Self::Output {
219 True
220 }
221 }
222 impl<B> ops::BitOr<B> for False {
223 type Output = B;
224 fn bitor(self, v: B) -> Self::Output {
225 v
226 }
227 }
228
229 impl<B: Boolean> ops::BitXor<B> for True
230 where
231 Not<B>: Boolean
232 {
233 type Output = Not<B>;
234
235 fn bitxor(self, _: B) -> Self::Output {
236 #[cfg(feature = "const_default")]
237 {
238 Not::<B>::DEFAULT
239 }
240 #[cfg(not(feature = "const_default"))]
241 {
242 Not::<B>::default()
243 }
244 }
245 }
246 impl<B> ops::BitXor<B> for False {
247 type Output = B;
248 fn bitxor(self, v: B) -> Self::Output {
249 v
250 }
251 }
252}
253
254/// Negates a [Boolean](./trait.Boolean.html).
255///
256/// # use core_extensions::type_level_bool::*;
257/// assert_eq!(Not::<True >::VALUE, false);
258/// assert_eq!(Not::<False>::VALUE, true);
259///
260pub type Not<T> = <T as ops::Not>::Output;
261
262/// `And`s two [Boolean](./trait.Boolean.html)s
263///
264///
265/// # use core_extensions::type_level_bool::*;
266/// assert_eq!(And::<True , True >::VALUE, true);
267/// assert_eq!(And::<False, True >::VALUE, false);
268/// assert_eq!(And::<True , False>::VALUE, false);
269/// assert_eq!(And::<False, False>::VALUE, false);
270///
271pub type And<L, R> = <L as ops::BitAnd<R>>::Output;
272
273/// `Or`s two [Boolean](./trait.Boolean.html)s
274///
275///
276/// # use core_extensions::type_level_bool::*;
277/// assert_eq!(Or::<True , True >::VALUE, true);
278/// assert_eq!(Or::<False, True >::VALUE, true);
279/// assert_eq!(Or::<True , False>::VALUE, true);
280/// assert_eq!(Or::<False, False>::VALUE, false);
281///
282pub type Or<L, R> = <L as ops::BitOr<R>>::Output;
283
284/// `Xor`s two [Boolean](./trait.Boolean.html)s
285///
286///
287/// # use core_extensions::type_level_bool::*;
288/// assert_eq!(Xor::<True , True >::VALUE, false);
289/// assert_eq!(Xor::<False, True >::VALUE, true);
290/// assert_eq!(Xor::<True , False>::VALUE, true);
291/// assert_eq!(Xor::<False, False>::VALUE, false);
292///
293pub type Xor<L, R> = <L as ops::BitXor<R>>::Output;