objc2/macros/
extern_conformance.rs

1/// Implement a protocol for an external class.
2///
3/// This creates a given protocol implementation with regards to the
4/// type-system. Useful on types created with [`extern_class!`], not use this
5/// on custom classes created with [`define_class!`], instead, implement the
6/// protocol within that macro.
7///
8/// [`define_class!`]: crate::define_class!
9///
10/// # Examples
11///
12/// ```
13/// # #[cfg(not_available)]
14/// use objc2_foundation::NSObjectProtocol;
15/// # use objc2::runtime::NSObjectProtocol;
16/// use objc2::runtime::NSObject;
17/// use objc2::{extern_class, extern_conformance};
18///
19/// extern_class!(
20///     #[unsafe(super(NSObject))]
21///     #[derive(PartialEq, Eq, Hash, Debug)]
22///     pub struct MyClass;
23/// );
24///
25/// // SAFETY: The class `MyClass` conforms to the `NSObject` protocol (since
26/// // its superclass `NSObject` does).
27/// extern_conformance!(unsafe impl NSObjectProtocol for MyClass {});
28/// ```
29///
30/// See the [`extern_class!`] macro for more examples.
31///
32/// [`extern_class!`]: crate::extern_class!
33#[doc(alias = "@interface")]
34#[macro_export]
35macro_rules! extern_conformance {
36    (unsafe impl $(<$($t:ident : $($bound:ident)? $(?$sized:ident)? $(+ $b:path)*),* $(,)?>)? $ty:ident for $protocol:ty {}) => {
37        unsafe impl $(<$($t : $($bound)? $(?$sized)? $(+ $b)*),*>)? $ty for $protocol {
38            // TODO(breaking): Add private marker here.
39        }
40    };
41}
42
43#[cfg(test)]
44mod tests {
45    use crate::runtime::NSObject;
46    use crate::{extern_class, extern_protocol};
47
48    extern_class!(
49        #[unsafe(super(NSObject))]
50        #[name = "NSObject"]
51        struct OldSyntax;
52    );
53
54    extern_protocol!(
55        #[name = "NSObjectProtocol"]
56        #[allow(clippy::missing_safety_doc)]
57        unsafe trait Protocol {}
58    );
59
60    // Old syntax, must continue to work until next breaking version.
61    unsafe impl Protocol for OldSyntax {}
62}