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) => {{
101        <[(); { $bool as usize }] as $crate::ConstBool>::VALUE
102    }};
103    // (tern: $?
104    // "ternary dsl for ops?"
105}
106#[doc(inline)]
107pub use const_logic;
108
109
110/// Converts a *const* `bool` expression to a type-level boolean.
111///
112/// Internally, it leverages the [`ConstBool`] trait and a trick related to array sizes:
113/// - Arrays of size `[(); 0]` are mapped to [`False`].
114/// - Arrays of size `[(); 1]` are mapped to [`True`].
115///
116/// # Examples
117/// ```
118/// # use devela::{const_bool, True};
119/// const _: True = const_bool![4 == 4];
120/// ```
121/// ```compile_fail
122/// # use devela::{const_bool, True};
123/// const _: True = const_bool![3 == 4];
124/// ```
125#[macro_export]
126#[cfg_attr(cargo_primary_package, doc(hidden))]
127macro_rules! const_bool {
128    ($bool:expr) => {{
129        <[(); { $bool as usize }] as $crate::ConstBool>::VALUE
130    }};
131}
132#[doc(inline)]
133pub use const_bool;
134
135/// A type-level logical *true*.
136///
137/// The second state in binary and ternary logic.
138///
139/// See also the [`ConstBool`] trait, the [`const_bool`] macro, and the [`False`] type.
140#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
141pub struct True;
142
143/// A type-level logical *false*.
144///
145/// The first state in binary and ternary logic.
146///
147/// See also the [`ConstBool`] trait, the [`const_bool`] macro, and the [`True`] type.
148#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
149pub struct False;
150
151/// A type-level logical *maybe*.
152///
153/// The third state in ternary logic.
154///
155/// See also the [`ConstTrool`] trait, the [`const_trool!`] macro,
156/// and the [`True`] and [`False`] types.
157#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
158pub struct Maybe;
159
160
161/// Binary
162#[rustfmt::skip]
163impl False {
164    /// Applies the `not` operation, (returns `True`).
165    pub const fn not(self) -> True { True }
166    /// Applies the `not` operation, (returns `True`).
167    pub const fn not_ref(&self) -> &'static True { &True }
168
169    /// Applies the `and` operation to `_other`, (returns `False`).
170    pub fn and<T>(self, _other: T) -> False { False }
171    /// Applies the `and` operation to `_other`, (returns `False`).
172    pub const fn and_ref<T>(&self, _other: &T) -> &'static False { &False }
173
174    /// Applies the `or` operation to `other`, (returns `other`).
175    pub fn or<T>(self, other: T) -> T { other }
176    /// Applies the `or` operation to `other`, (returns `other`).
177    pub const fn or_ref<'a, T>(&self, other: &'a T) -> &'a T { other }
178
179    /// Returns the value as `bool` (returns `false`).
180    pub const fn value(self) -> bool { false }
181    /// Returns the value as `bool` (returns `false`).
182    pub const fn value_ref(&self) -> bool { false }
183}
184/// Binary
185#[rustfmt::skip]
186impl True {
187    /// Applies the `not` operation, (returns `False`).
188    pub const fn not(self) -> False { False }
189    /// Applies the `not` operation, (returns `False`).
190    pub const fn not_ref(&self) -> &'static False { &False }
191
192    /// Applies the `and` operation to `other`, (returns `other`).
193    pub const fn and<T>(self, other: T) -> T { other }
194    /// Applies the `and` operation to `other`, (returns `other`).
195    pub const fn and_ref<'a, T>(&self, other: &'a T) -> &'a T { other }
196
197    /// Applies the `or` operation to `_other`, (returns `True`).
198    pub fn or<T>(self, _other: T) -> True { True }
199    /// Applies the `or` operation to `_other`, (returns `True`).
200    pub const fn or_ref<T>(&self, _other: &T) -> &'static True { &True }
201
202    /// Returns the value as `bool` (returns `true`).
203    pub const fn value(self) -> bool { true }
204    /// Returns the value as `bool` (returns `true`).
205    pub const fn value_ref(&self) -> bool { true }
206}
207
208// TODO
209// /// Ternary
210// impl Maybe {
211// }
212/// Ternary
213impl False {
214}
215/// Ternary
216impl True {
217}