devela/num/logic/bool.rs
1// devela::code::bool::bool
2//
3//! Type-level booleans.
4//
5// TOC
6// - trait ConstBool
7// - macro const_bool!
8// - types True, False
9//
10// RETHINK TODO
11// - add
12
13// IDEA: https://github.com/paholg/typenum/issues/191
14/*
15pub trait TypeBool {
16}
17impl TypeBool for True {
18 type And<Other: TypeBool> = Other;
19 type Not = False;
20}
21impl TypeBool for False {
22 type And<Other: TypeBool> = False;
23 type Not = True;
24}
25*/
26
27use crate::sf;
28
29/// Allows to convert compile-time constants into type-level booleans.
30///
31/// See also the [`const_bool`] macro, and the [`True`] and [`False`] types.
32#[rustfmt::skip]
33#[diagnostic::on_unimplemented(
34 message = "Only expressions that evaluate to a constant 0 or 1 are valid for `ConstBool`.",
35 label = "This expression does not evaluate to a constant 0 or 1 (as usize)."
36)]
37pub trait ConstBool {
38 /// The resulting type-level boolean (`True` or `False`).
39 type Value: Sized;
40 /// The constant value of the type-level boolean.
41 const VALUE: Self::Value;
42
43 // IDEA?
44 // type And<Other: ConstBool>: ConstBool;
45 // type Not: ConstBool;
46}
47sf! {
48 impl ConstBool for False { type Value = False; const VALUE: Self::Value = False; }
49 impl ConstBool for [(); 0] { type Value = False; const VALUE: Self::Value = False; }
50 impl ConstBool for True { type Value = True; const VALUE: Self::Value = True; }
51 impl ConstBool for [(); 1] { type Value = True; const VALUE: Self::Value = True; }
52}
53
54/// Allows to convert compile-time constants into type-level trooleans.
55///
56/// See also the [`const_trool!`] macro, and the [`True`], [`False`] and [`Maybe`] types.
57#[rustfmt::skip]
58#[diagnostic::on_unimplemented(
59 message = "Only expressions that evaluate to a constant 0 or 1 are valid for `ConstBool`.",
60 label = "This expression does not evaluate to a constant 0 or 1 (as usize)."
61)]
62pub trait ConstTrool {
63 /// The resulting type-level boolean (`True` or `False`).
64 type Value: Sized;
65 /// The constant value of the type-level boolean.
66 const VALUE: Self::Value;
67
68 // IDEA?
69 // type And<Other: ConstBool>: ConstBool;
70 // type Not: ConstBool;
71}
72sf! {
73 impl ConstTrool for False { type Value = False; const VALUE: False = False; }
74 impl ConstTrool for [(); 0] { type Value = False; const VALUE: False = False; }
75 impl ConstTrool for True { type Value = True; const VALUE: True = True; }
76 impl ConstTrool for [(); 1] { type Value = True; const VALUE: True = True; }
77 impl ConstTrool for Maybe { type Value = Maybe; const VALUE: Maybe = Maybe; }
78 impl ConstTrool for [(); 2] { type Value = Maybe; const VALUE: Maybe = Maybe; }
79}
80
81/// MAYBE?
82// TODO: binary, ternary…
83pub trait ConstLogic<const N: usize> {
84 ///
85 type Value: Sized;
86 ///
87 const VALUE: Self::Value;
88}
89sf! {
90 impl ConstLogic<2> for False { type Value = False; const VALUE: False = False; }
91 impl ConstLogic<3> for False { type Value = False; const VALUE: False = False; }
92 impl ConstLogic<2> for True { type Value = True; const VALUE: True = True; }
93 impl ConstLogic<3> for True { type Value = True; const VALUE: True = True; }
94 impl ConstLogic<3> for Maybe { type Value = Maybe; const VALUE: Maybe = Maybe; }
95}
96/// MAYBE
97#[macro_export]
98#[cfg_attr(cargo_primary_package, doc(hidden))]
99macro_rules! const_logic {
100 (bool: $bool:expr) => {{ <[(); { $bool as usize }] as $crate::ConstBool>::VALUE }}; // (tern: $?
101 // "ternary dsl for ops?"
102}
103#[doc(inline)]
104pub use const_logic;
105
106/// Converts a *const* `bool` expression to a type-level boolean.
107///
108/// Internally, it leverages the [`ConstBool`] trait and a trick related to array sizes:
109/// - Arrays of size `[(); 0]` are mapped to [`False`].
110/// - Arrays of size `[(); 1]` are mapped to [`True`].
111///
112/// # Examples
113/// ```
114/// # use devela::{const_bool, True};
115/// const _: True = const_bool![4 == 4];
116/// ```
117/// ```compile_fail
118/// # use devela::{const_bool, True};
119/// const _: True = const_bool![3 == 4];
120/// ```
121#[macro_export]
122#[cfg_attr(cargo_primary_package, doc(hidden))]
123macro_rules! const_bool {
124 ($bool:expr) => {{ <[(); { $bool as usize }] as $crate::ConstBool>::VALUE }};
125}
126#[doc(inline)]
127pub use const_bool;
128
129/// A type-level logical *true*.
130///
131/// The second state in binary and ternary logic.
132///
133/// See also the [`ConstBool`] trait, the [`const_bool`] macro, and the [`False`] type.
134#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
135pub struct True;
136
137/// A type-level logical *false*.
138///
139/// The first state in binary and ternary logic.
140///
141/// See also the [`ConstBool`] trait, the [`const_bool`] macro, and the [`True`] type.
142#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
143pub struct False;
144
145/// A type-level logical *maybe*.
146///
147/// The third state in ternary logic.
148///
149/// See also the [`ConstTrool`] trait, the [`const_trool!`] macro,
150/// and the [`True`] and [`False`] types.
151#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
152pub struct Maybe;
153
154/// Binary
155#[rustfmt::skip]
156impl False {
157 /// Applies the `not` operation, (returns `True`).
158 pub const fn not(self) -> True { True }
159 /// Applies the `not` operation, (returns `True`).
160 pub const fn not_ref(&self) -> &'static True { &True }
161
162 /// Applies the `and` operation to `_other`, (returns `False`).
163 pub fn and<T>(self, _other: T) -> False { False }
164 /// Applies the `and` operation to `_other`, (returns `False`).
165 pub const fn and_ref<T>(&self, _other: &T) -> &'static False { &False }
166
167 /// Applies the `or` operation to `other`, (returns `other`).
168 pub fn or<T>(self, other: T) -> T { other }
169 /// Applies the `or` operation to `other`, (returns `other`).
170 pub const fn or_ref<'a, T>(&self, other: &'a T) -> &'a T { other }
171
172 /// Returns the value as `bool` (returns `false`).
173 pub const fn value(self) -> bool { false }
174 /// Returns the value as `bool` (returns `false`).
175 pub const fn value_ref(&self) -> bool { false }
176}
177/// Binary
178#[rustfmt::skip]
179impl True {
180 /// Applies the `not` operation, (returns `False`).
181 pub const fn not(self) -> False { False }
182 /// Applies the `not` operation, (returns `False`).
183 pub const fn not_ref(&self) -> &'static False { &False }
184
185 /// Applies the `and` operation to `other`, (returns `other`).
186 pub const fn and<T>(self, other: T) -> T { other }
187 /// Applies the `and` operation to `other`, (returns `other`).
188 pub const fn and_ref<'a, T>(&self, other: &'a T) -> &'a T { other }
189
190 /// Applies the `or` operation to `_other`, (returns `True`).
191 pub fn or<T>(self, _other: T) -> True { True }
192 /// Applies the `or` operation to `_other`, (returns `True`).
193 pub const fn or_ref<T>(&self, _other: &T) -> &'static True { &True }
194
195 /// Returns the value as `bool` (returns `true`).
196 pub const fn value(self) -> bool { true }
197 /// Returns the value as `bool` (returns `true`).
198 pub const fn value_ref(&self) -> bool { true }
199}
200
201// TODO
202// /// Ternary
203// impl Maybe {
204// }
205/// Ternary
206impl False {}
207/// Ternary
208impl True {}