Skip to main content

rustypy/pytypes/
pybool.rs

1//! Analog to a Python boolean type.
2//!
3//! It supports & and | operators, and comparison to Rust bool types.
4//! To return to Python use the ```into_raw``` method and return a raw pointer.
5//!
6//! # Safety
7//! You can convert a raw pointer to a bool type with ```from_ptr_into_bool``` method,
8//! or to a ```&PyBool``` with ```from_ptr``` method. Those operations are unsafe as they require
9//! dereferencing a raw pointer.
10//!
11//! # Examples
12//!
13//! ```
14//! use rustypy::PyBool;
15//! let pybool = PyBool::from(true);
16//! assert_eq!(pybool, true);
17//!
18//! // prepare to return to Python:
19//! let ptr = pybool.into_raw();
20//! // convert from raw pointer to a bool
21//! let rust_bool = unsafe { PyBool::from_ptr_into_bool(ptr) };
22//! ```
23use libc::c_char;
24
25use std::convert::From;
26use std::ops::{BitAnd, BitOr, Not};
27
28/// Analog to a Python boolean type.
29///
30/// Read the [module docs](index.html) for more information.
31#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)]
32pub struct PyBool {
33    val: i8,
34}
35
36impl PyBool {
37    /// Get a PyBool from a previously boxed raw pointer.
38    pub unsafe fn from_ptr(ptr: *mut PyBool) -> PyBool {
39        *(Box::from_raw(ptr))
40    }
41
42    /// Creates a bool from a raw pointer to a PyBool.
43    pub unsafe fn from_ptr_into_bool(ptr: *mut PyBool) -> bool {
44        let ptr: &PyBool = &*ptr;
45        match ptr.val {
46            0 => false,
47            _ => true,
48        }
49    }
50
51    /// Conversion from PyBool to bool.
52    pub fn to_bool(self) -> bool {
53        match self.val {
54            0 => false,
55            _ => true,
56        }
57    }
58
59    /// Returns PyBool as a raw pointer. Use this whenever you want to return
60    /// a PyBool to Python.
61    pub fn into_raw(self) -> *mut PyBool {
62        Box::into_raw(Box::new(self))
63    }
64
65    /// Sets value of the underlying bool
66    pub fn load(&mut self, v: bool) {
67        if v {
68            self.val = 1
69        } else {
70            self.val = 0
71        }
72    }
73}
74
75#[doc(hidden)]
76#[no_mangle]
77pub unsafe extern "C" fn pybool_free(ptr: *mut PyBool) {
78    if ptr.is_null() {
79        return;
80    }
81    Box::from_raw(ptr);
82}
83
84#[doc(hidden)]
85#[no_mangle]
86pub extern "C" fn pybool_new(val: c_char) -> *mut PyBool {
87    let val = match val {
88        0 => 0,
89        _ => 1,
90    };
91    let pystr = PyBool { val };
92    pystr.into_raw()
93}
94
95#[doc(hidden)]
96#[no_mangle]
97pub unsafe extern "C" fn pybool_get_val(ptr: *mut PyBool) -> i8 {
98    let pybool = &*ptr;
99    pybool.val
100}
101
102impl From<PyBool> for bool {
103    fn from(b: PyBool) -> bool {
104        b.to_bool()
105    }
106}
107
108impl From<bool> for PyBool {
109    fn from(b: bool) -> PyBool {
110        let val = if b { 1 } else { 0 };
111        PyBool { val }
112    }
113}
114
115impl<'a> From<&'a bool> for PyBool {
116    fn from(b: &'a bool) -> PyBool {
117        let val = if *b { 1 } else { 0 };
118        PyBool { val }
119    }
120}
121
122impl From<i8> for PyBool {
123    fn from(b: i8) -> PyBool {
124        let val = match b {
125            0 => 0,
126            _ => 1,
127        };
128        PyBool { val }
129    }
130}
131
132impl PartialEq<bool> for PyBool {
133    fn eq(&self, other: &bool) -> bool {
134        (self.val == 0 && !(*other)) || (self.val == 1 && *other)
135    }
136}
137
138impl<'a> PartialEq<bool> for &'a PyBool {
139    fn eq(&self, other: &bool) -> bool {
140        (self.val == 0 && !(*other)) || (self.val == 1 && *other)
141    }
142}
143
144impl Not for PyBool {
145    type Output = bool;
146    fn not(self) -> bool {
147        match self.val {
148            0 => false,
149            _ => true,
150        }
151    }
152}
153
154impl BitAnd<bool> for PyBool {
155    type Output = bool;
156    fn bitand(self, rhs: bool) -> bool {
157        let val = match self.val {
158            0 => false,
159            _ => true,
160        };
161        val & rhs
162    }
163}
164
165impl<'a> BitAnd<bool> for &'a PyBool {
166    type Output = bool;
167    fn bitand(self, rhs: bool) -> bool {
168        let val = match self.val {
169            0 => false,
170            _ => true,
171        };
172        val & rhs
173    }
174}
175
176impl<'a> BitAnd<&'a bool> for PyBool {
177    type Output = bool;
178    fn bitand(self, rhs: &'a bool) -> bool {
179        let val = match self.val {
180            0 => false,
181            _ => true,
182        };
183        val & rhs
184    }
185}
186
187impl<'a, 'b> BitAnd<&'a bool> for &'b PyBool {
188    type Output = bool;
189    fn bitand(self, rhs: &'a bool) -> bool {
190        let val = match self.val {
191            0 => false,
192            _ => true,
193        };
194        val & rhs
195    }
196}
197
198impl BitOr<bool> for PyBool {
199    type Output = bool;
200    fn bitor(self, rhs: bool) -> bool {
201        let val = match self.val {
202            0 => false,
203            _ => true,
204        };
205        val | rhs
206    }
207}
208
209impl<'a> BitOr<bool> for &'a PyBool {
210    type Output = bool;
211    fn bitor(self, rhs: bool) -> bool {
212        let val = match self.val {
213            0 => false,
214            _ => true,
215        };
216        val | rhs
217    }
218}
219
220impl<'a> BitOr<&'a bool> for PyBool {
221    type Output = bool;
222    fn bitor(self, rhs: &'a bool) -> bool {
223        let val = match self.val {
224            0 => false,
225            _ => true,
226        };
227        val | rhs
228    }
229}
230
231impl<'a, 'b> BitOr<&'a bool> for &'b PyBool {
232    type Output = bool;
233    fn bitor(self, rhs: &'a bool) -> bool {
234        let val = match self.val {
235            0 => false,
236            _ => true,
237        };
238        val | rhs
239    }
240}