extendr_api/scalar/
rbool.rs1use crate::scalar::macros::*;
2use crate::*;
3use std::convert::TryFrom;
4
5#[repr(transparent)]
13#[readonly::make]
14pub struct Rbool(pub i32);
15
16impl Rbool {
17 pub fn new(val: i32) -> Self {
18 Rbool(val)
19 }
20
21 pub const fn true_value() -> Rbool {
23 Rbool(1)
24 }
25
26 pub const fn false_value() -> Rbool {
28 Rbool(0)
29 }
30
31 pub const fn na_value() -> Rbool {
33 Rbool(i32::MIN)
34 }
35
36 pub fn is_true(&self) -> bool {
38 self.0 != 0 && !self.is_na()
39 }
40
41 pub fn is_false(&self) -> bool {
43 self.0 == 0 && !self.is_na()
44 }
45
46 pub fn to_bool(&self) -> bool {
48 self.0 != 0
49 }
50
51 pub fn from_bool(val: bool) -> Self {
53 Rbool(val as i32)
54 }
55}
56
57gen_trait_impl!(Rbool, bool, |x: &Rbool| x.0 == i32::MIN, i32::MIN);
58gen_from_primitive!(Rbool, i32);
59gen_partial_ord!(Rbool, bool);
60
61impl From<bool> for Rbool {
62 fn from(v: bool) -> Self {
63 Rbool(i32::from(v))
64 }
65}
66
67impl From<Option<bool>> for Rbool {
68 fn from(v: Option<bool>) -> Self {
69 if let Some(v) = v {
70 Rbool::from(v)
71 } else {
72 Rbool::na()
73 }
74 }
75}
76
77impl From<Rbool> for Option<bool> {
78 fn from(v: Rbool) -> Self {
79 if v.0.is_na() {
80 None
81 } else {
82 Some(v.0 != 0)
83 }
84 }
85}
86
87impl From<Rbool> for bool {
88 fn from(v: Rbool) -> Self {
89 v.0 != 0
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}