1use crate::{Decimal, Double, Float, Integer};
2use std::fmt;
3use std::str::{FromStr, ParseBoolError};
4
5#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
9#[repr(transparent)]
10pub struct Boolean {
11 value: bool,
12}
13
14impl Boolean {
15 #[inline]
17 #[must_use]
18 pub fn is_identical_with(self, other: Self) -> bool {
19 self == other
20 }
21}
22
23impl From<bool> for Boolean {
24 #[inline]
25 fn from(value: bool) -> Self {
26 Self { value }
27 }
28}
29
30impl From<Integer> for Boolean {
31 #[inline]
32 fn from(value: Integer) -> Self {
33 (value != Integer::from(0)).into()
34 }
35}
36
37impl From<Decimal> for Boolean {
38 #[inline]
39 fn from(value: Decimal) -> Self {
40 (value != Decimal::from(0)).into()
41 }
42}
43
44impl From<Float> for Boolean {
45 #[inline]
46 fn from(value: Float) -> Self {
47 (value != Float::from(0.) && !value.is_nan()).into()
48 }
49}
50
51impl From<Double> for Boolean {
52 #[inline]
53 fn from(value: Double) -> Self {
54 (value != Double::from(0.) && !value.is_nan()).into()
55 }
56}
57
58impl From<Boolean> for bool {
59 #[inline]
60 fn from(value: Boolean) -> Self {
61 value.value
62 }
63}
64
65impl FromStr for Boolean {
66 type Err = ParseBoolError;
67
68 #[inline]
69 fn from_str(input: &str) -> Result<Self, Self::Err> {
70 Ok(match input {
71 "true" | "1" => true,
72 "false" | "0" => false,
73 _ => bool::from_str(input)?,
74 }
75 .into())
76 }
77}
78
79impl fmt::Display for Boolean {
80 #[inline]
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 self.value.fmt(f)
83 }
84}
85
86#[cfg(test)]
87#[allow(clippy::panic_in_result_fn)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn from_str() -> Result<(), ParseBoolError> {
93 assert_eq!(Boolean::from_str("true")?.to_string(), "true");
94 assert_eq!(Boolean::from_str("1")?.to_string(), "true");
95 assert_eq!(Boolean::from_str("false")?.to_string(), "false");
96 assert_eq!(Boolean::from_str("0")?.to_string(), "false");
97 Ok(())
98 }
99
100 #[test]
101 fn from_integer() {
102 assert_eq!(Boolean::from(false), Integer::from(0).into());
103 assert_eq!(Boolean::from(true), Integer::from(1).into());
104 assert_eq!(Boolean::from(true), Integer::from(2).into());
105 }
106
107 #[test]
108 fn from_decimal() {
109 assert_eq!(Boolean::from(false), Decimal::from(0).into());
110 assert_eq!(Boolean::from(true), Decimal::from(1).into());
111 assert_eq!(Boolean::from(true), Decimal::from(2).into());
112 }
113
114 #[test]
115 fn from_float() {
116 assert_eq!(Boolean::from(false), Float::from(0.).into());
117 assert_eq!(Boolean::from(true), Float::from(1.).into());
118 assert_eq!(Boolean::from(true), Float::from(2.).into());
119 assert_eq!(Boolean::from(false), Float::from(f32::NAN).into());
120 assert_eq!(Boolean::from(true), Float::from(f32::INFINITY).into());
121 }
122
123 #[test]
124 fn from_double() {
125 assert_eq!(Boolean::from(false), Double::from(0.).into());
126 assert_eq!(Boolean::from(true), Double::from(1.).into());
127 assert_eq!(Boolean::from(true), Double::from(2.).into());
128 assert_eq!(Boolean::from(false), Double::from(f64::NAN).into());
129 assert_eq!(Boolean::from(true), Double::from(f64::INFINITY).into());
130 }
131}