objc_sys/
types.rs

1//! Objective-C type aliases.
2
3use crate::{objc_object, objc_selector};
4
5/// The BOOL typedef for Apple's objc4.
6///
7/// Don't be fooled by the backup definition in `objc.h`; __OBJC_BOOL_IS_BOOL
8/// is always defined by `clang` when compiling Objective-C sources. The below
9/// cfgs are determined experimentally via. cross compiling.
10///
11/// See also <https://www.jviotti.com/2024/01/05/is-objective-c-bool-a-boolean-type-it-depends.html>.
12#[cfg(all(not(feature = "gnustep-1-7"), not(feature = "unstable-objfw")))]
13mod inner {
14    // __OBJC_BOOL_IS_BOOL
15    #[cfg(any(
16        // aarch64-apple-*
17        target_arch = "aarch64",
18        // + x86_64-apple-ios (i.e. the simulator) (but not x86_64-apple-ios-macabi)
19        all(target_os = "ios", target_pointer_width = "64", not(target_abi_macabi)),
20        // + x86_64-apple-tvos
21        all(target_os = "tvos", target_pointer_width = "64"),
22        // + *-apple-watchos
23        target_os = "watchos",
24    ))]
25    // C: _Bool
26    pub(crate) type BOOL = bool;
27
28    // Inverse of the above
29    #[cfg(not(any(
30        target_arch = "aarch64",
31        all(target_os = "ios", target_pointer_width = "64", not(target_abi_macabi)),
32        all(target_os = "tvos", target_pointer_width = "64"),
33        target_os = "watchos",
34    )))]
35    // C: (explicitly) signed char
36    pub(crate) type BOOL = i8;
37}
38
39// GNUStep's and Microsoft's libobjc2
40#[cfg(all(feature = "gnustep-1-7", libobjc2_strict_apple_compat))]
41mod inner {
42    // C: (explicitly) signed char
43    pub(crate) type BOOL = i8;
44}
45
46#[cfg(all(feature = "gnustep-1-7", not(libobjc2_strict_apple_compat)))]
47mod inner {
48    // windows && !32bit-MinGW
49    #[cfg(all(windows, not(all(target_pointer_width = "64", target_env = "gnu"))))]
50    pub(crate) type BOOL = std::os::raw::c_int;
51
52    // The inverse
53    #[cfg(not(all(windows, not(all(target_pointer_width = "64", target_env = "gnu")))))]
54    // C: unsigned char
55    pub(crate) type BOOL = u8;
56}
57
58// ObjFW
59#[cfg(feature = "unstable-objfw")]
60mod inner {
61    // Defined in ObjFW-RT.h
62    // C: signed char
63    // This has changed since v0.90, but we don't support that yet.
64    pub(crate) type BOOL = i8;
65
66    // Note that ObjFW usually uses `bool` in return types, but that doesn't
67    // change the ABI, so we'll use `BOOL` there as well, for ease of use.
68}
69
70/// The Objective-C `BOOL` type.
71///
72/// The type of this varies across platforms, so to convert an it into a Rust
73/// [`bool`], compare it with [`NO`][crate::NO].
74///
75/// Note that this does _not_ implement `objc2::Encode` on all platforms! You
76/// should only use this on FFI boundaries, otherwise prefer
77/// `objc2::runtime::Bool`.
78///
79/// See also the [corresponding documentation entry][docs].
80///
81/// [docs]: https://developer.apple.com/documentation/objectivec/bool?language=objc
82pub type BOOL = inner::BOOL;
83
84// # Why isize/usize is correct for NSInteger/NSUInteger
85//
86// ## Apple
87// The documentation clearly states:
88//
89// > When building 32-bit applications, NSInteger is a 32-bit integer. A
90//   64-bit application treats NSInteger as a 64-bit integer.
91//
92// And the header file defines them like so:
93//
94//     #if __LP64__ || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
95//     typedef long NSInteger;
96//     typedef unsigned long NSUInteger;
97//     #else
98//     typedef int NSInteger;
99//     typedef unsigned int NSUInteger;
100//     #endif
101//
102// Rust (or at least `libc`) has no targets where c_int/c_uint are not 32-bit,
103// so that part is correct. By manual inspection it is found that the only
104// platform where c_long/c_ulong differs from isize/usize is on Windows.
105// However Apple's libraries are only designed to work on 32-bit Windows, so
106// this case should be fine as well.
107//
108// Likewise for NSUInteger.
109//
110//
111// ## GNUStep / WinObjC
112//
113// Defined as intptr_t/uintptr_t, which is exactly the same as isize/usize.
114//
115//
116// ## ObjFW
117//
118// Doesn't define these, but e.g. -[OFString length] returns size_t, so our
119// definitions should be correct on effectively all targets.
120//
121// Things might change slightly in the future, see
122// <https://internals.rust-lang.org/t/pre-rfc-usize-is-not-size-t/15369>.
123
124/// A signed integer value type.
125///
126/// This is guaranteed to always be a type-alias to [`isize`]. That means it
127/// is valid to use `#[repr(isize)]` on enums and structs with size
128/// `NSInteger`.
129///
130/// See also the [corresponding documentation entry][docs].
131///
132/// [docs]: https://developer.apple.com/documentation/objectivec/nsinteger?language=objc
133///
134///
135/// # Examples
136///
137/// ```
138/// use core::mem::size_of;
139/// # use objc_sys::NSInteger;
140/// # #[cfg(not_available)]
141/// use objc2::ffi::NSInteger;
142///
143/// #[repr(isize)]
144/// pub enum NSComparisonResult {
145///     NSOrderedAscending = -1,
146///     NSOrderedSame = 0,
147///     NSOrderedDescending = 1,
148/// }
149///
150/// assert_eq!(size_of::<NSComparisonResult>(), size_of::<NSInteger>());
151/// ```
152pub type NSInteger = isize;
153
154/// Describes an unsigned integer.
155///
156/// This is guaranteed to always be a type-alias to [`usize`]. That means it
157/// is valid to use `#[repr(usize)]` on enums and structs with size
158/// `NSUInteger`.
159///
160/// See also the [corresponding documentation entry][docs].
161///
162/// [docs]: https://developer.apple.com/documentation/objectivec/nsuinteger?language=objc
163///
164///
165/// # Examples
166///
167/// ```
168/// # use objc_sys::NSUInteger;
169/// # #[cfg(not_available)]
170/// use objc2::ffi::NSUInteger;
171///
172/// extern "C" {
173///     fn some_external_function() -> NSUInteger;
174/// }
175/// ```
176///
177/// ```
178/// use core::mem::size_of;
179/// # use objc_sys::NSUInteger;
180/// # #[cfg(not_available)]
181/// use objc2::ffi::NSUInteger;
182///
183/// #[repr(usize)]
184/// enum CLRegionState {
185///     Unknown = 0,
186///     Inside = 1,
187///     Outside = 2,
188/// }
189///
190/// assert_eq!(size_of::<CLRegionState>(), size_of::<NSUInteger>());
191/// ```
192pub type NSUInteger = usize;
193
194/// The maximum value for a [`NSInteger`].
195pub const NSIntegerMax: NSInteger = NSInteger::MAX;
196
197/// The minimum value for a [`NSInteger`].
198pub const NSIntegerMin: NSInteger = NSInteger::MIN;
199
200/// The maximum value for a [`NSUInteger`].
201pub const NSUIntegerMax: NSUInteger = NSUInteger::MAX;
202
203/// An immutable pointer to a selector.
204///
205/// Type alias provided for convenience. See `objc2::runtime::Sel` for a
206/// higher level binding.
207pub type SEL = *const objc_selector;
208
209/// A mutable pointer to an object / instance.
210///
211/// Type alias provided for convenience. You'll likely want to use one of:
212/// - `objc2_foundation::NS[...]` for when you know the class of the object
213///   you're dealing with.
214/// - `objc2::rc::Retained` for a proper way of doing memory management.
215/// - `objc2::runtime::AnyObject` for a bit safer representation of this.
216pub type id = *mut objc_object;