From 8d9627ebfee8898e4c4507f095fa10ebfaf159dd Mon Sep 17 00:00:00 2001 From: Shaheen Gandhi Date: Wed, 6 Jan 2021 00:49:04 -0800 Subject: [PATCH 1/2] [WIP] Add generics support to objective-c class definition --- src/core/macros.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++ src/objc/macros.rs | 33 +++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/core/macros.rs b/src/core/macros.rs index d202be8..f96593c 100644 --- a/src/core/macros.rs +++ b/src/core/macros.rs @@ -1,5 +1,8 @@ // This macro is intentionally undocumented to ensure it is not publicly // exported. + +#![feature(log_syntax)] + macro_rules! subclass { ( $(#[$meta:meta])+ @@ -59,6 +62,64 @@ macro_rules! subclass { } } }; + ( + $(#[$meta:meta])+ + $vis:vis class $a:ident <$lifetime:lifetime, $genty:ident> : $b:ty ; + ) => { + $(#[$meta])+ + #[repr(C)] + $vis struct $a <$lifetime, $genty> ($b, std::marker::PhantomData<&$lifetime $genty>); + + impl <$lifetime, $genty> $crate::core::ObjectType for $a <$lifetime, $genty> { + #[inline] + fn retain(obj: &Self) -> $crate::core::Arc { + let obj = $crate::core::Arc::retain(&obj.0); + unsafe { $crate::core::Arc::cast_unchecked(obj) } + } + + #[inline] + unsafe fn release(obj: std::ptr::NonNull) { + <$b>::release(obj.cast()); + } + } + + impl <$lifetime, $genty> std::ops::Deref for $a <$lifetime, $genty> { + type Target = $b; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl <$lifetime, $genty> AsRef<$a <$lifetime, $genty>> for $a <$lifetime, $genty> { + #[inline] + fn as_ref(&self) -> &Self { + self + } + } + + impl <$lifetime, $genty> AsMut<$a <$lifetime, $genty>> for $a <$lifetime, $genty> { + #[inline] + fn as_mut(&mut self) -> &mut Self { + self + } + } + + impl <$lifetime, $genty, _T> AsRef<_T> for $a <$lifetime, $genty> where $b: AsRef<_T> { + #[inline] + fn as_ref(&self) -> &_T { + self.0.as_ref() + } + } + + impl <$lifetime, $genty, _T> AsMut<_T> for $a <$lifetime, $genty> where $b: AsMut<_T> { + #[inline] + fn as_mut(&mut self) -> &mut _T { + self.0.as_mut() + } + } + }; } // This macro is intentionally undocumented to ensure it is not publicly diff --git a/src/objc/macros.rs b/src/objc/macros.rs index 3d32129..68a84fb 100644 --- a/src/objc/macros.rs +++ b/src/objc/macros.rs @@ -1,4 +1,23 @@ macro_rules! objc_class_type { + ($obj:ident <$lifetime:lifetime, $genty:ident>) => { + objc_class_type!($obj <$lifetime, $genty>, stringify!($obj)); + }; + ($obj:ident <$lifetime:lifetime, $genty:ident>, $class:expr) => { + objc_class_type!(@processed_generic + $obj <$lifetime, $genty>, + $class, + concat!("OBJC_CLASS_$_", $class) + ); + }; + (@processed_generic $obj:ident <$lifetime:lifetime, $genty:ident>, $class:expr, $class_symbol:expr) => { + impl<$lifetime, $genty> $crate::objc::ClassType<$lifetime> for $obj<$lifetime, $genty> + where $genty: $crate::objc::ObjectType<$lifetime> { + #[inline] + fn class() -> &'static $crate::objc::Class { + $crate::_objc_class!(@ $class_symbol) + } + } + }; ($obj:ident $(<$lifetime:lifetime>)?) => { objc_class_type!($obj $(<$lifetime>)?, stringify!($obj)); }; @@ -58,6 +77,20 @@ macro_rules! objc_subclass { objc_class_type!($a <$lifetime>); }; + ( + $(#[$meta:meta])+ + $vis:vis class $a:ident <$lifetime:lifetime, $genty:ident> : $b:ty ; + ) => { + subclass! { + $(#[$meta])+ + $vis class $a <$lifetime, $genty> : $b ; + } + + impl<$lifetime, $genty> $crate::objc::ObjectType<$lifetime> for $a<$lifetime, $genty> + where $genty: $crate::objc::ObjectType<$lifetime> {} + + objc_class_type!($a <$lifetime, $genty>); + }; } // This macro is intentionally undocumented to ensure it is not publicly From b56d819a1d848c156dea8c22f769b8798f7102cf Mon Sep 17 00:00:00 2001 From: Shaheen Gandhi Date: Sat, 9 Jan 2021 17:43:01 -0800 Subject: [PATCH 2/2] [WIP] Add NSArray --- src/foundation/mod.rs | 2 ++ src/foundation/ns_array/macros.rs | 6 ++++++ src/foundation/ns_array/mod.rs | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 src/foundation/ns_array/macros.rs create mode 100644 src/foundation/ns_array/mod.rs diff --git a/src/foundation/mod.rs b/src/foundation/mod.rs index 5df0022..3861041 100644 --- a/src/foundation/mod.rs +++ b/src/foundation/mod.rs @@ -17,6 +17,7 @@ pub mod error_codes; mod cmp; mod geometry; +mod ns_array; mod ns_error; mod ns_exception; mod ns_null; @@ -26,6 +27,7 @@ mod ns_value; pub use cmp::*; pub use geometry::*; +pub use ns_array::*; pub use ns_error::*; pub use ns_exception::*; pub use ns_null::*; diff --git a/src/foundation/ns_array/macros.rs b/src/foundation/ns_array/macros.rs new file mode 100644 index 0000000..a43fbc8 --- /dev/null +++ b/src/foundation/ns_array/macros.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! ns_array { + ($s: expr) => {{ + + }} +} diff --git a/src/foundation/ns_array/mod.rs b/src/foundation/ns_array/mod.rs new file mode 100644 index 0000000..3e2b497 --- /dev/null +++ b/src/foundation/ns_array/mod.rs @@ -0,0 +1,22 @@ +use crate::core::Arc; +use crate::core::ObjectType; +use crate::objc::{NSObject, NSUInteger}; + +objc_subclass! { + /// A static ordered collection of objects. + /// + // See [documentation](https://developer.apple.com/documentation/foundation/nsarray?language=objc) + pub class NSArray<'data, T>: NSObject<'data>; +} + +impl<'a, T: ObjectType> NSArray<'a, T> { + /// The number of objects in the array. + pub fn count(&self) -> NSUInteger { + unsafe { _msg_send_any![self, count] } + } + + /// Returns the object located at the specified index. + pub fn object_at_index(&self, index: NSUInteger) -> Arc { + unsafe { _msg_send_any![self, object_at_index: index] } + } +}