Skip to main content

mtl_foundation/
set.rs

1//! Set type for Foundation.
2//!
3//! Corresponds to `Foundation/NSSet.hpp`.
4//!
5//! # C++ Equivalent
6//!
7//! ```cpp
8//! namespace NS {
9//! class Set : public NS::Copying<Set> {
10//! public:
11//!     UInteger count() const;
12//!     Enumerator<Object>* objectEnumerator() const;
13//!     static Set* alloc();
14//!     Set* init();
15//!     Set* init(const Object* const* pObjects, UInteger count);
16//!     Set* init(const class Coder* pCoder);
17//! };
18//! }
19//! ```
20
21use std::ffi::c_void;
22use std::marker::PhantomData;
23use std::ptr::NonNull;
24
25use mtl_sys::{class, msg_send_0, msg_send_1, msg_send_2, sel};
26
27use crate::enumerator::Enumerator;
28use crate::object::{Copying, Object, Referencing};
29use crate::types::UInteger;
30
31/// An Objective-C set object.
32///
33/// C++ equivalent: `NS::Set`
34#[repr(transparent)]
35pub struct Set<T = Object> {
36    inner: NonNull<c_void>,
37    _marker: PhantomData<T>,
38}
39
40impl<T> Clone for Set<T> {
41    fn clone(&self) -> Self {
42        Self {
43            inner: self.inner,
44            _marker: PhantomData,
45        }
46    }
47}
48
49impl<T> Set<T> {
50    /// Get the count of objects in the set.
51    ///
52    /// C++ equivalent: `UInteger count() const`
53    #[inline]
54    pub fn count(&self) -> UInteger {
55        unsafe { msg_send_0(self.as_ptr(), sel!(count)) }
56    }
57
58    /// Get an enumerator for the objects in the set.
59    ///
60    /// C++ equivalent: `Enumerator<Object>* objectEnumerator() const`
61    #[inline]
62    pub fn object_enumerator(&self) -> Option<Enumerator<T>> {
63        unsafe {
64            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(objectEnumerator));
65            Enumerator::from_ptr(ptr)
66        }
67    }
68
69    /// Allocate a new set.
70    ///
71    /// C++ equivalent: `static Set* alloc()`
72    #[inline]
73    pub fn alloc() -> Option<Self> {
74        unsafe {
75            let ptr: *mut c_void = msg_send_0(class!(NSSet).as_ptr(), sel!(alloc));
76            Self::from_ptr(ptr)
77        }
78    }
79
80    /// Initialize an allocated set.
81    ///
82    /// C++ equivalent: `Set* init()`
83    #[inline]
84    pub fn init(&self) -> Option<Self> {
85        unsafe {
86            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
87            Self::from_ptr(ptr)
88        }
89    }
90
91    /// Initialize with multiple objects.
92    ///
93    /// C++ equivalent: `Set* init(const Object* const* pObjects, UInteger count)`
94    #[inline]
95    pub fn init_with_objects(&self, objects: *const *const T, count: UInteger) -> Option<Self> {
96        unsafe {
97            let ptr: *mut c_void =
98                msg_send_2(self.as_ptr(), sel!(initWithObjects:count:), objects, count);
99            Self::from_ptr(ptr)
100        }
101    }
102
103    /// Initialize with a coder.
104    ///
105    /// C++ equivalent: `Set* init(const class Coder* pCoder)`
106    #[inline]
107    pub fn init_with_coder(&self, coder: *const c_void) -> Option<Self> {
108        unsafe {
109            let ptr: *mut c_void = msg_send_1(self.as_ptr(), sel!(initWithCoder:), coder);
110            Self::from_ptr(ptr)
111        }
112    }
113
114    /// Create a Set from a raw pointer.
115    ///
116    /// # Safety
117    ///
118    /// The pointer must be a valid Objective-C NSSet object.
119    #[inline]
120    pub unsafe fn from_ptr(ptr: *mut c_void) -> Option<Self> {
121        NonNull::new(ptr).map(|inner| Self {
122            inner,
123            _marker: PhantomData,
124        })
125    }
126}
127
128impl<T> Referencing for Set<T> {
129    #[inline]
130    fn as_ptr(&self) -> *const c_void {
131        self.inner.as_ptr()
132    }
133}
134
135impl<T> Copying for Set<T> {
136    #[inline]
137    fn copy(&self) -> Option<Self> {
138        unsafe {
139            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
140            Self::from_ptr(ptr)
141        }
142    }
143}
144
145unsafe impl<T: Send> Send for Set<T> {}
146unsafe impl<T: Sync> Sync for Set<T> {}
147
148impl<T> std::fmt::Debug for Set<T> {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150        f.debug_struct("Set")
151            .field("ptr", &self.inner)
152            .field("count", &self.count())
153            .finish()
154    }
155}
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_set_size() {
163        assert_eq!(
164            std::mem::size_of::<Set<Object>>(),
165            std::mem::size_of::<*mut c_void>()
166        );
167    }
168}