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()
}
}
}