1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use objc2::rc::{Id, Owned, Ownership};
use objc2::{msg_send, Message};

pub unsafe trait NSCopying: Message {
    /// Indicates whether the type is mutable or immutable.
    ///
    /// This can be [`Owned`] if and only if `copy` creates a new instance,
    /// see the following example:
    ///
    /// ```ignore
    /// let x: Id<MyObject, _> = MyObject::new();
    /// // This is valid only if `y` is a new instance. Otherwise `x` and `y`
    /// // would be able to create aliasing mutable references!
    /// let y: Id<MyObject, Owned> = x.copy();
    /// ```
    ///
    /// Note that for the same reason, you should be careful when defining
    /// `new` methods on your object; e.g. immutable types like [`NSString`]
    /// don't return `Id<NSString, Owned>`, because that would allow this
    /// trait to create an aliasing `Id<NSString, Shared>` (since sending the
    /// `copy` message (and others) does not create a new instance, but
    /// instead just retains the instance).
    ///
    /// [`NSString`]: crate::NSString
    type Ownership: Ownership;

    /// The output type.
    ///
    /// This is usually `Self`, but e.g. `NSMutableString` returns `NSString`.
    /// TODO: Verify???
    type Output: Message;

    fn copy(&self) -> Id<Self::Output, Self::Ownership> {
        unsafe {
            let obj: *mut Self::Output = msg_send![self, copy];
            Id::new(obj).unwrap()
        }
    }
}

/// TODO
///
/// Note that the `mutableCopy` selector must return an owned object!
pub unsafe trait NSMutableCopying: Message {
    /// TODO
    type Output: Message;

    fn mutable_copy(&self) -> Id<Self::Output, Owned> {
        unsafe {
            let obj: *mut Self::Output = msg_send![self, mutableCopy];
            Id::new(obj).unwrap()
        }
    }
}