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}