1
1
/// Create a new type to represent an Objective-C class.
2
2
///
3
- /// The given name should correspond to a valid Objective-C class, whose
4
- /// instances have the encoding `Encoding::Object` (as an example:
5
- /// `NSAutoreleasePool` does not have this).
3
+ /// This is similar to an `@interface` declaration in Objective-C.
4
+ ///
5
+ /// The given struct name should correspond to a valid Objective-C class,
6
+ /// whose instances have the encoding [`objc2::Encoding::Object`].
7
+ /// (as an example: `NSAutoreleasePool` does not have this!)
8
+ ///
9
+ /// You must specify the superclass of this class, similar to how you would
10
+ /// in Objective-C. Due to Rust trait limitations, specifying e.g. the
11
+ /// superclass `NSData` would not give you easy access to `NSObject`'s
12
+ /// functionality, therefore you may specify additional parts of the
13
+ /// inheritance chain.
6
14
///
7
15
///
8
16
/// # Specification
9
17
///
10
- /// This creates an opaque struct, and implements traits for it to allow
11
- /// easier usage as an Objective-C object.
18
+ /// This creates an opaque struct containing the superclass (which means that
19
+ /// auto traits are inherited from the superclass), and implements the
20
+ /// following traits for it to allow easier usage as an Objective-C object:
12
21
///
13
- /// The traits [`objc2::RefEncode`] and [`objc2::Message`] are implemented to
14
- /// allow sending messages to the object and using it in [`objc2::rc::Id`].
22
+ /// - [`objc2::RefEncode`]
23
+ /// - [`objc2::Message`]
24
+ /// - [`Deref<Target = $superclass>`][core::ops::Deref]
25
+ /// - [`DerefMut`][core::ops::DerefMut]
26
+ /// - [`AsRef<$inheritance_chain>`][AsRef]
27
+ /// - [`AsMut<$inheritance_chain>`][AsMut]
28
+ /// - [`Borrow<$inheritance_chain>`][core::borrow::Borrow]
29
+ /// - [`BorrowMut<$inheritance_chain>`][core::borrow::BorrowMut]
15
30
///
16
31
/// An associated function `class` is created on the object as a convenient
17
32
/// shorthand so that you can do `MyObject::class()` instead of
18
33
/// `class!(MyObject)`.
19
34
///
20
- /// [`Deref`] and [`DerefMut`] are implemented and delegate to the first
21
- /// superclass (direct parent). Auto traits are inherited from this superclass
22
- /// as well (this macro effectively just creates a newtype wrapper around the
23
- /// superclass).
24
- ///
25
- /// Finally, [`AsRef`], [`AsMut`], [`Borrow`] and [`BorrowMut`] are
26
- /// implemented to allow conversion to an arbitary superclasses in the
27
- /// inheritance chain (since an instance of a class can always be interpreted
28
- /// as its superclasses).
35
+ /// The macro allows specifying fields on the struct, but _only_ zero-sized
36
+ /// types like [`PhantomData`] and [`objc2::declare::Ivar`] are allowed here!
29
37
///
30
- /// [`Deref`]: core::ops::Deref
31
- /// [`DerefMut`]: core::ops::DerefMut
32
- /// [`Borrow`]: core::borrow::Borrow
33
- /// [`BorrowMut`]: core::borrow::BorrowMut
38
+ /// [`PhantomData`]: core::marker::PhantomData
34
39
///
35
40
///
36
41
/// # Safety
37
42
///
38
- /// The specified inheritance chain must be correct, including in the correct
39
- /// order, and the types in said chain must be valid as Objective-C objects
40
- /// (this is easy to ensure by also creating those using this macro ).
43
+ /// The specified superclass must be correct. The object must also respond to
44
+ /// standard memory management messages (this is upheld if `NSObject` is part
45
+ /// of its inheritance chain ).
41
46
///
42
- /// The object must respond to standard memory management messages (this is
43
- /// upheld if `NSObject` is part of its inheritance chain).
47
+ /// Additionally, any fields (if specified) must be zero-sized.
44
48
///
45
49
///
46
50
/// # Example
90
94
/// ```
91
95
///
92
96
/// See the source code of `objc2_foundation` in general for more examples.
97
+ #[ doc( alias = "@interface" ) ]
93
98
#[ macro_export]
94
99
macro_rules! extern_class {
95
100
(
96
101
$( #[ $m: meta] ) *
97
- unsafe $v: vis struct $name: ident: $( $inheritance_chain : ty) ,+ ;
102
+ unsafe $v: vis struct $name: ident: $superclass : ty $ ( , $inheritance_rest : ty) * ;
98
103
) => {
99
- $crate:: __inner_extern_class! {
100
- @__inner
104
+ $crate:: extern_class! {
101
105
$( #[ $m] ) *
102
- unsafe $v struct $name<> : $( $inheritance_chain , ) + $crate :: objc2 :: runtime :: Object { }
106
+ unsafe $v struct $name: $superclass $ ( , $inheritance_rest ) * { }
103
107
}
104
-
105
- impl $name {
106
- # [ doc = concat! (
107
- "Get a reference to the Objective-C class `" ,
108
- stringify! ( $name ) ,
109
- "`." ,
110
- ) ]
111
- # [ inline ]
112
- // TODO: Allow users to configure this?
113
- $v fn class ( ) -> & ' static $crate :: objc2 :: runtime :: Class {
114
- $crate :: objc2 :: class! ( $name )
108
+ } ;
109
+ (
110
+ $ ( # [ $m : meta ] ) *
111
+ unsafe $v : vis struct $name : ident : $superclass : ty $ ( , $inheritance_rest : ty ) * {
112
+ $ ( $field_vis : vis $field : ident : $field_ty : ty , ) *
113
+ }
114
+ ) => {
115
+ $crate :: __inner_extern_class! {
116
+ $ ( # [ $m ] ) *
117
+ unsafe $v struct $name<> : $superclass $ ( , $inheritance_rest ) * {
118
+ $( $field_vis $field : $field_ty , ) *
115
119
}
116
120
}
117
121
} ;
@@ -198,15 +202,15 @@ macro_rules! __inner_extern_class {
198
202
(
199
203
@__inner
200
204
$( #[ $m: meta] ) *
201
- unsafe $v: vis struct $name: ident<$( $t: ident $( : $b: ident) ?) ,* >: $inherits : ty $( , $inheritance_rest: ty) * {
205
+ unsafe $v: vis struct $name: ident<$( $t: ident $( : $b: ident) ?) ,* >: $superclass : ty $( , $inheritance_rest: ty) * {
202
206
$( $p_v: vis $p: ident: $pty: ty, ) *
203
207
}
204
208
) => {
205
209
$( #[ $m] ) *
206
210
// TODO: repr(transparent) when the inner pointer is no longer a ZST.
207
211
#[ repr( C ) ]
208
212
$v struct $name<$( $t $( : $b) ?) ,* > {
209
- __inner: $inherits ,
213
+ __inner: $superclass ,
210
214
// Additional fields (should only be zero-sized PhantomData or ivars).
211
215
$( $p_v $p: $pty) ,*
212
216
}
@@ -219,7 +223,7 @@ macro_rules! __inner_extern_class {
219
223
// the layout.
220
224
unsafe impl <$( $t $( : $b) ?) ,* > $crate:: objc2:: RefEncode for $name<$( $t) ,* > {
221
225
const ENCODING_REF : $crate:: objc2:: Encoding <' static >
222
- = <$inherits as $crate:: objc2:: RefEncode >:: ENCODING_REF ;
226
+ = <$superclass as $crate:: objc2:: RefEncode >:: ENCODING_REF ;
223
227
}
224
228
225
229
// SAFETY: This is essentially just a newtype wrapper over `Object`
@@ -249,7 +253,7 @@ macro_rules! __inner_extern_class {
249
253
// the same object, `x: &T` and `y: &T::Target`, and this would be
250
254
// perfectly safe!
251
255
impl <$( $t $( : $b) ?) ,* > $crate:: __core:: ops:: Deref for $name<$( $t) ,* > {
252
- type Target = $inherits ;
256
+ type Target = $superclass ;
253
257
254
258
#[ inline]
255
259
fn deref( & self ) -> & Self :: Target {
@@ -289,6 +293,6 @@ macro_rules! __inner_extern_class {
289
293
}
290
294
}
291
295
292
- $crate:: __impl_as_ref_borrow!( $name<$( $t $( : $b) ?) ,* >, $inherits , $( $inheritance_rest, ) * ) ;
296
+ $crate:: __impl_as_ref_borrow!( $name<$( $t $( : $b) ?) ,* >, $superclass , $( $inheritance_rest, ) * ) ;
293
297
} ;
294
298
}
0 commit comments