diff --git a/objc2-foundation-sys/src/generated_nsstring.rs b/objc2-foundation-sys/src/generated_nsstring.rs index 2df6e5654..c6eaa6255 100644 --- a/objc2-foundation-sys/src/generated_nsstring.rs +++ b/objc2-foundation-sys/src/generated_nsstring.rs @@ -10,7 +10,7 @@ use objc2::rc::{Id, Unknown}; use objc2::runtime::{Bool, Object}; use objc2::{class, msg_send, Encoding, Message, RefEncode}; -use crate::{Autoreleased, NSArray, NSObject}; +use crate::{Autoreleased, NSArray, NSData, NSObject}; pub type NSRange = [NSUInteger; 2]; pub type NSComparisonResult = NSInteger; @@ -18,7 +18,6 @@ pub type NSComparisonResult = NSInteger; pub type NSCoder = NSObject; pub type NSLocale = NSObject; pub type NSError = NSObject; -pub type NSData = NSObject; pub type NSDictionary = NSObject; pub type NSCharacterSet = NSObject; pub type NSURL = NSObject; diff --git a/objc2-foundation-sys/src/generated_others_shim.rs b/objc2-foundation-sys/src/generated_others_shim.rs index bcb42adec..94a843015 100644 --- a/objc2-foundation-sys/src/generated_others_shim.rs +++ b/objc2-foundation-sys/src/generated_others_shim.rs @@ -3,6 +3,8 @@ use core::mem::ManuallyDrop; use core::ptr::NonNull; +use std::os::raw::c_void; + use objc2::ffi::{NSInteger, NSUInteger}; use objc2::rc::{Id, Unknown}; use objc2::runtime::Object; @@ -55,8 +57,12 @@ impl NSArray { let this = ManuallyDrop::new(this); Id::new(msg_send![this, initWithObjects: objects, count: cnt]) } - pub unsafe fn initWithCoder_(&self, coder: NonNull) -> Option> { - Id::new_null(msg_send![self, initWithCoder: coder]) + pub unsafe fn initWithCoder_( + this: Id, + coder: NonNull, + ) -> Option> { + let this = ManuallyDrop::new(this); + Id::new_null(msg_send![this, initWithCoder: coder]) } pub unsafe fn count(&self) -> NSUInteger { msg_send![self, count] @@ -71,3 +77,60 @@ impl NSArray { msg_send![self, getObjects: objects, range: range] } } + +#[repr(transparent)] +pub struct NSData(NSObject); +impl core::ops::Deref for NSData { + type Target = NSObject; + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl core::ops::DerefMut for NSData { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} +unsafe impl Message for NSData {} +unsafe impl RefEncode for NSData { + const ENCODING_REF: Encoding<'static> = Encoding::Object; +} +impl NSData { + pub unsafe fn alloc() -> Option> { + Id::new_null(msg_send![class!(NSData), alloc]) + } +} +impl NSData { + pub unsafe fn length(&self) -> NSUInteger { + msg_send![self, length] + } + pub unsafe fn bytes(&self) -> *const c_void { + msg_send![self, bytes] + } +} +impl NSData { + pub unsafe fn initWithBytes_length_( + this: Id, + bytes: *const c_void, + length: NSUInteger, + ) -> Id { + let this = ManuallyDrop::new(this); + Id::new(msg_send![this, initWithBytes: bytes, length: length]) + } + pub unsafe fn initWithBytesNoCopy_length_deallocator_( + this: Id, + bytes: *mut c_void, + length: NSUInteger, + deallocator: *mut c_void, + ) -> Id { + let this = ManuallyDrop::new(this); + Id::new(msg_send![ + this, + initWithBytesNoCopy: bytes, + length: length, + deallocator: deallocator, + ]) + } +} diff --git a/objc2-foundation/src/data.rs b/objc2-foundation/src/data.rs index aed26318b..aaa92d20a 100644 --- a/objc2-foundation/src/data.rs +++ b/objc2-foundation/src/data.rs @@ -4,7 +4,7 @@ use core::ops::{Deref, DerefMut, Range}; use core::slice; use core::{ffi::c_void, ptr::NonNull}; -use super::{INSCopying, INSMutableCopying, INSObject, NSRange}; +use super::{ffi, INSCopying, INSMutableCopying, INSObject, NSRange}; use objc2::msg_send; use objc2::rc::{Id, Owned, Ownership, Shared}; @@ -13,8 +13,12 @@ pub unsafe trait INSData: INSObject { unsafe_def_fn!(fn new -> Self::Ownership); + fn r(&self) -> &ffi::NSData { + unsafe { &*(self as *const Self as *const ffi::NSData) } + } + fn len(&self) -> usize { - unsafe { msg_send![self, length] } + unsafe { self.r().length() } } fn is_empty(&self) -> bool { @@ -22,26 +26,21 @@ pub unsafe trait INSData: INSObject { } fn bytes(&self) -> &[u8] { - let ptr: *const c_void = unsafe { msg_send![self, bytes] }; + let ptr = unsafe { self.r().bytes() } as *const u8; // The bytes pointer may be null for length zero if ptr.is_null() { &[] } else { - unsafe { slice::from_raw_parts(ptr as *const u8, self.len()) } + unsafe { slice::from_raw_parts(ptr, self.len()) } } } fn with_bytes(bytes: &[u8]) -> Id { - let cls = Self::class(); let bytes_ptr = bytes.as_ptr() as *const c_void; unsafe { - let obj: *mut Self = msg_send![cls, alloc]; - let obj: *mut Self = msg_send![ - obj, - initWithBytes: bytes_ptr, - length: bytes.len(), - ]; - Id::new(NonNull::new_unchecked(obj)) + let obj = ffi::NSData::alloc().unwrap(); + let obj = ffi::NSData::initWithBytes_length_(obj, bytes_ptr, bytes.len()); + obj.cast().into_ownership() } } @@ -66,28 +65,28 @@ pub unsafe trait INSData: INSObject { // See https://github.com/gnustep/libs-base/pull/213 // So we just use NSDataWithDeallocatorBlock directly. #[cfg(gnustep)] - let cls = { + let obj = { let cls = Self::class(); - if cls == objc2::class!(NSData) { + let cls = if cls == objc2::class!(NSData) { objc2::class!(NSDataWithDeallocatorBlock) } else { cls - } + }; + unsafe { Id::new_null(msg_send![cls, alloc]) }.unwrap() }; #[cfg(not(gnustep))] - let cls = Self::class(); + let obj = unsafe { ffi::NSData::alloc() }.unwrap(); let mut bytes = ManuallyDrop::new(bytes); unsafe { - let obj: *mut Self = msg_send![cls, alloc]; - let obj: *mut Self = msg_send![ + let obj = ffi::NSData::initWithBytesNoCopy_length_deallocator_( obj, - initWithBytesNoCopy: bytes.as_mut_ptr() as *mut c_void, - length: bytes.len(), - deallocator: dealloc, - ]; - Id::new(NonNull::new_unchecked(obj)) + bytes.as_mut_ptr().cast(), + bytes.len(), + dealloc as *const _ as *mut c_void, + ); + obj.cast().into_ownership() } } }