eh/lib.rs
1//! Convert values to `bool`, kind of like C, eh?
2//!
3//! [`Eh`] roughly follows the implicit conversion rules for [C to `_Bool`][C]
4//! or [C++ to `bool`][C++], but Rust requires an explicit conversion. Integer
5//! `0`, floating-point `0.0`, and null pointers are `false`, and all other
6//! values are `true`.
7//!
8//! [`Eh`]: trait.Eh.html
9//! [C]: https://en.cppreference.com/w/c/language/conversion#Boolean_conversion
10//! [C++]: https://en.cppreference.com/w/cpp/language/implicit_conversion#Boolean_conversions
11//!
12//! As a Rust-specific extension, this is also implemented for `Option<T>` and
13//! `Result<T, E>`. It returns `true` when the `?` operator would unwrap a `T`
14//! value, and `false` when `?` would cause an early return.
15//!
16//! ## Examples
17//!
18//! Boolean values just return themselves.
19//!
20//! ```
21//! use eh::Eh;
22//! assert!(true.eh());
23//! assert!(true.eh().eh());
24//! assert!(!(false.eh()));
25//! ```
26//!
27//! Integers are `true` for all non-zero values.
28//!
29//! ```
30//! use eh::Eh;
31//! use std::i32;
32//! assert!(1.eh());
33//! assert!((-1).eh());
34//! assert!(i32::MIN.eh());
35//! assert!(i32::MAX.eh());
36//! assert!(!(0.eh()));
37//! ```
38//!
39//! Wrapping integers follow the same rules.
40//!
41//! ```
42//! use eh::Eh;
43//! use std::num::Wrapping;
44//! assert!(Wrapping(1).eh());
45//! assert!(!(Wrapping(0).eh()));
46//! ```
47//!
48//! Floats are also `true` for all non-zero values -- including NaN!
49//!
50//! ```
51//! use eh::Eh;
52//! use std::f64;
53//! assert!(1.0.eh());
54//! assert!((-1.0).eh());
55//! assert!(f64::EPSILON.eh());
56//! assert!(f64::INFINITY.eh());
57//! assert!(f64::NAN.eh());
58//! assert!(!(0.0.eh()));
59//! assert!(!(-0.0).eh());
60//! ```
61//!
62//! Raw pointers are `true` for any non-null value, without dereferencing.
63//!
64//! ```
65//! use eh::Eh;
66//! use std::ptr;
67//! assert!((&0 as *const i32).eh());
68//! assert!((&mut 0 as *mut i32).eh());
69//! assert!(ptr::NonNull::<i32>::dangling().as_ptr().eh());
70//! assert!(!ptr::null::<i32>().eh());
71//! assert!(!ptr::null_mut::<i32>().eh());
72//! ```
73//!
74//! Options are `true` for any `Some` value, and `false` for `None`.
75//!
76//! ```
77//! use eh::Eh;
78//! assert!(Some(0).eh());
79//! assert!(Some(1).eh());
80//! assert!(!None::<i32>.eh());
81//! ```
82//!
83//! Results are `true` for any `Ok` value, and `false` for any `Err` value.
84//!
85//! ```
86//! use eh::Eh;
87//! assert!(Ok::<i32, i32>(0).eh());
88//! assert!(Ok::<i32, i32>(1).eh());
89//! assert!(!Err::<i32, i32>(0).eh());
90//! assert!(!Err::<i32, i32>(1).eh());
91//! ```
92//!
93//! ## Exclusions
94//!
95//! `Eh` does not implement further boolean conversions of other languages,
96//! especially since they're not universal. For example:
97//!
98//! - JavaScript converts NaN to `false`, different than C and C++ (and `eh`).
99//! - JavaScript converts empty `[]` and `{}` to `true`, but in Python they're `false`.
100//! - Many languages convert empty strings to `false` and non-empty strings to `true`,
101//! but `"0"` is also `false` in Perl and PHP.
102//!
103//! ## About
104//!
105//! The name is a play on the [Canadian "eh"][eh], turning a declarative
106//! sentence into a question.
107//!
108//! [eh]: https://en.wikipedia.org/wiki/Eh#Canada
109
110#![no_std]
111
112/// Convert values to `bool`, kind of like C, eh?
113pub trait Eh {
114 fn eh(&self) -> bool;
115}
116
117impl Eh for bool {
118 #[inline]
119 fn eh(&self) -> bool {
120 *self
121 }
122}
123
124macro_rules! int_eh {
125 ($($T:ty),*) => {$(
126 impl Eh for $T {
127 #[inline]
128 fn eh(&self) -> bool {
129 *self != 0
130 }
131 }
132 )*}
133}
134int_eh! { i8, i16, i32, i64, i128, isize }
135int_eh! { u8, u16, u32, u64, u128, usize }
136
137macro_rules! float_eh {
138 ($($T:ty),*) => {$(
139 impl Eh for $T {
140 #[inline]
141 fn eh(&self) -> bool {
142 *self != 0.0
143 }
144 }
145 )*}
146}
147float_eh! { f32, f64 }
148
149impl<T: ?Sized> Eh for *const T {
150 #[inline]
151 fn eh(&self) -> bool {
152 !self.is_null()
153 }
154}
155
156impl<T: ?Sized> Eh for *mut T {
157 #[inline]
158 fn eh(&self) -> bool {
159 !self.is_null()
160 }
161}
162
163impl<T: Eh> Eh for core::num::Wrapping<T> {
164 #[inline]
165 fn eh(&self) -> bool {
166 self.0.eh()
167 }
168}
169
170impl<T> Eh for Option<T> {
171 #[inline]
172 fn eh(&self) -> bool {
173 self.is_some()
174 }
175}
176
177impl<T, E> Eh for Result<T, E> {
178 #[inline]
179 fn eh(&self) -> bool {
180 self.is_ok()
181 }
182}