1
- use crate :: { ffi, Encode , Encoding , RefEncode } ;
1
+ //! This belongs in `objc2`, but it is put here to make `EncodeConvert` work
2
+ //! properly!
2
3
use core:: fmt;
3
4
5
+ use crate :: { Encode , EncodeConvert , Encoding , RefEncode } ;
6
+
4
7
/// The Objective-C `BOOL` type.
5
8
///
6
9
/// This is a thin wrapper-type over [`objc_sys::BOOL`]. It is intended that
7
10
/// you convert this into a Rust [`bool`] with the [`Bool::as_bool`] method as
8
11
/// soon as possible.
9
12
///
10
- /// This is FFI-safe and can be used in directly with
11
- /// [`msg_send!`][`crate::msg_send`] .
13
+ /// This is FFI-safe and can be used directly with `msg_send!` and `extern`
14
+ /// functions .
12
15
///
13
16
/// Note that this is able to contain more states than `bool` on some
14
17
/// platforms, but these cases should not be relied on!
15
- ///
16
- /// # Example
17
- ///
18
- /// ```no_run
19
- /// use objc2::{class, msg_send_bool, msg_send_id};
20
- /// use objc2::rc::{Id, Shared};
21
- /// use objc2::runtime::{Object, Bool};
22
- /// let ns_value: Id<Object, Shared> = unsafe {
23
- /// msg_send_id![class!(NSNumber), numberWithBool: Bool::YES]
24
- /// };
25
- /// assert!(unsafe { msg_send_bool![&ns_value, boolValue] });
26
- /// ```
27
18
#[ repr( transparent) ]
28
19
// We don't implement comparison traits because they could be implemented with
29
20
// two slightly different semantics:
@@ -32,62 +23,60 @@ use core::fmt;
32
23
// And it is not immediately clear for users which one was chosen.
33
24
#[ derive( Copy , Clone , Default ) ]
34
25
pub struct Bool {
35
- value : ffi :: BOOL ,
26
+ value : objc_sys :: BOOL ,
36
27
}
37
28
38
29
impl Bool {
39
30
/// The equivalent of [`true`] for Objective-C's `BOOL` type.
40
- pub const YES : Self = Self :: from_raw ( ffi :: YES ) ;
31
+ pub const YES : Self = Self :: from_raw ( objc_sys :: YES ) ;
41
32
42
33
/// The equivalent of [`false`] for Objective-C's `BOOL` type.
43
- pub const NO : Self = Self :: from_raw ( ffi :: NO ) ;
34
+ pub const NO : Self = Self :: from_raw ( objc_sys :: NO ) ;
44
35
45
36
/// Creates an Objective-C boolean from a Rust boolean.
46
37
#[ inline]
47
38
pub const fn new ( value : bool ) -> Self {
48
- // true as u8 => 1
49
- // false as u8 => 0
50
- let value = value as ffi :: BOOL ;
39
+ // true as BOOL => 1 (YES)
40
+ // false as BOOL => 0 (NO)
41
+ let value = value as objc_sys :: BOOL ;
51
42
Self { value }
52
43
}
53
44
54
45
/// Creates this from a boolean value received from a raw Objective-C API.
55
46
#[ inline]
56
- pub const fn from_raw ( value : ffi :: BOOL ) -> Self {
47
+ pub const fn from_raw ( value : objc_sys :: BOOL ) -> Self {
57
48
Self { value }
58
49
}
59
50
60
51
/// Retrieves the inner [`objc_sys::BOOL`] boolean type, to be used in raw
61
52
/// Objective-C APIs.
62
53
#[ inline]
63
- pub const fn as_raw ( self ) -> ffi :: BOOL {
54
+ pub const fn as_raw ( self ) -> objc_sys :: BOOL {
64
55
self . value
65
56
}
66
57
67
- /// Returns `true` if `self` is [`NO`][` Self::NO` ].
58
+ /// Returns `true` if `self` is [`NO`][Self::NO].
68
59
///
69
- /// You should prefer using [`as_bool`][` Self::as_bool` ].
60
+ /// You should prefer using [`as_bool`][Self::as_bool].
70
61
#[ inline]
71
62
pub const fn is_false ( self ) -> bool {
72
- // Always compare with 0
73
- // This is what happens with the `!` operator in C.
74
- self . value as u8 == 0
63
+ !self . as_bool ( )
75
64
}
76
65
77
- /// Returns `true` if `self` is the opposite of [`NO`][` Self::NO` ].
66
+ /// Returns `true` if `self` is not [`NO`][Self::NO].
78
67
///
79
- /// You should prefer using [`as_bool`][` Self::as_bool` ].
68
+ /// You should prefer using [`as_bool`][Self::as_bool].
80
69
#[ inline]
81
70
pub const fn is_true ( self ) -> bool {
82
- // Always compare with 0
83
- // This is what happens when using `if` in C.
84
- self . value as u8 != 0
71
+ self . as_bool ( )
85
72
}
86
73
87
74
/// Converts this into the [`bool`] equivalent.
88
75
#[ inline]
89
76
pub const fn as_bool ( self ) -> bool {
90
- self . is_true ( )
77
+ // Always compare with 0 (NO)
78
+ // This is what happens with the `!` operator / when using `if` in C.
79
+ self . value != objc_sys:: NO
91
80
}
92
81
}
93
82
@@ -113,7 +102,11 @@ impl fmt::Debug for Bool {
113
102
114
103
// SAFETY: `Bool` is `repr(transparent)`.
115
104
unsafe impl Encode for Bool {
116
- const ENCODING : Encoding = ffi:: BOOL :: ENCODING ;
105
+ // i8::__ENCODING == Encoding::Char
106
+ // u8::__ENCODING == Encoding::UChar
107
+ // bool::__ENCODING == Encoding::Bool
108
+ // i32::__ENCODING == Encoding::Int
109
+ const ENCODING : Encoding = objc_sys:: BOOL :: __ENCODING;
117
110
}
118
111
119
112
// Note that we shouldn't delegate to `BOOL`'s `ENCODING_REF` since `BOOL` is
@@ -185,14 +178,13 @@ mod tests {
185
178
assert_eq ! ( format!( "{:?}" , Bool :: from( false ) ) , "NO" ) ;
186
179
}
187
180
188
- // Can't really do this test since it won't compile on platforms where
189
- // type BOOL = bool.
190
- //
191
- // #[test]
192
- // fn test_outside_normal() {
193
- // let b = Bool::from_raw(42);
194
- // assert!(b.is_true());
195
- // assert!(!b.is_false());
196
- // assert_eq!(b.as_raw(), 42);
197
- // }
181
+ #[ test]
182
+ // Test on platform where we know the type of BOOL
183
+ #[ cfg( all( feature = "apple" , target_os = "macos" , target_arch = "x86_64" ) ) ]
184
+ fn test_outside_normal ( ) {
185
+ let b = Bool :: from_raw ( 42 ) ;
186
+ assert ! ( b. is_true( ) ) ;
187
+ assert ! ( !b. is_false( ) ) ;
188
+ assert_eq ! ( b. as_raw( ) , 42 ) ;
189
+ }
198
190
}
0 commit comments