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 std::ops::Not for Rbool {
88 type Output = Self;
89
90 fn not(self) -> Self::Output {
91 if self.is_na() {
92 Rbool::na()
93 } else if self.is_true() {
94 Rbool::false_value()
95 } else {
96 Rbool::true_value()
97 }
98 }
99}
100
101impl std::fmt::Debug for Rbool {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 write!(
104 f,
105 "{}",
106 if self.is_na() {
107 "NA_LOGICAL"
108 } else if self.is_true() {
109 "TRUE"
110 } else {
111 "FALSE"
112 }
113 )
114 }
115}
116
117impl TryFrom<&Robj> for Rbool {
118 type Error = Error;
119
120 fn try_from(robj: &Robj) -> Result<Self> {
123 if let Some(v) = robj.as_logical_slice() {
124 match v.len() {
125 0 => Err(Error::ExpectedNonZeroLength(robj.clone())),
126 1 => Ok(v[0]),
127 _ => Err(Error::ExpectedScalar(robj.clone())),
128 }
129 } else {
130 Err(Error::ExpectedLogical(robj.clone()))
131 }
132 }
133}