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 {}