extendr_api/scalar/
rbool.rs
1use crate::scalar::macros::*;
2use crate::scalar::Scalar;
3use crate::*;
4use std::convert::TryFrom;
5
6#[repr(transparent)]
14pub struct Rbool(i32);
15
16impl Scalar<i32> for Rbool {
17 fn inner(&self) -> i32 {
18 self.0
19 }
20
21 fn new(val: i32) -> Self {
22 Rbool(val)
23 }
24}
25
26impl Rbool {
27 pub const fn true_value() -> Rbool {
29 Rbool(1)
30 }
31
32 pub const fn false_value() -> Rbool {
34 Rbool(0)
35 }
36
37 pub const fn na_value() -> Rbool {
39 Rbool(i32::MIN)
40 }
41
42 pub fn is_true(&self) -> bool {
44 self.inner() != 0 && !self.is_na()
45 }
46
47 pub fn is_false(&self) -> bool {
49 self.inner() == 0 && !self.is_na()
50 }
51
52 pub fn to_bool(&self) -> bool {
54 self.inner() != 0
55 }
56
57 pub fn from_bool(val: bool) -> Self {
59 Rbool(val as i32)
60 }
61}
62
63gen_trait_impl!(Rbool, bool, |x: &Rbool| x.inner() == i32::MIN, i32::MIN);
64gen_from_primitive!(Rbool, i32);
65gen_partial_ord!(Rbool, bool);
66
67impl From<bool> for Rbool {
68 fn from(v: bool) -> Self {
69 Rbool(i32::from(v))
70 }
71}
72
73impl From<Option<bool>> for Rbool {
74 fn from(v: Option<bool>) -> Self {
75 if let Some(v) = v {
76 Rbool::from(v)
77 } else {
78 Rbool::na()
79 }
80 }
81}
82
83impl From<Rbool> for Option<bool> {
84 fn from(v: Rbool) -> Self {
85 if v.inner().is_na() {
86 None
87 } else {
88 Some(v.inner() != 0)
89 }
90 }
91}
92
93impl std::ops::Not for Rbool {
94 type Output = Self;
95
96 fn not(self) -> Self::Output {
97 if self.is_na() {
98 Rbool::na()
99 } else if self.is_true() {
100 Rbool::false_value()
101 } else {
102 Rbool::true_value()
103 }
104 }
105}
106
107impl std::fmt::Debug for Rbool {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 write!(
110 f,
111 "{}",
112 if self.is_na() {
113 "NA_LOGICAL"
114 } else if self.is_true() {
115 "TRUE"
116 } else {
117 "FALSE"
118 }
119 )
120 }
121}
122
123impl TryFrom<&Robj> for Rbool {
124 type Error = Error;
125
126 fn try_from(robj: &Robj) -> Result<Self> {
129 if let Some(v) = robj.as_logical_slice() {
130 match v.len() {
131 0 => Err(Error::ExpectedNonZeroLength(robj.clone())),
132 1 => Ok(v[0]),
133 _ => Err(Error::ExpectedScalar(robj.clone())),
134 }
135 } else {
136 Err(Error::ExpectedLogical(robj.clone()))
137 }
138 }
139}