Skip to content

Commit

Permalink
Add a few NSData methods
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Dec 21, 2021
1 parent 31052e3 commit 3457bd3
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 27 deletions.
3 changes: 1 addition & 2 deletions objc2-foundation-sys/src/generated_nsstring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ 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;

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;
Expand Down
67 changes: 65 additions & 2 deletions objc2-foundation-sys/src/generated_others_shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<NSCoder>) -> Option<Id<Self, Unknown>> {
Id::new_null(msg_send![self, initWithCoder: coder])
pub unsafe fn initWithCoder_(
this: Id<Self, Unknown>,
coder: NonNull<NSCoder>,
) -> Option<Id<Self, Unknown>> {
let this = ManuallyDrop::new(this);
Id::new_null(msg_send![this, initWithCoder: coder])
}
pub unsafe fn count(&self) -> NSUInteger {
msg_send![self, count]
Expand All @@ -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<Self, Unknown>> {
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<Self, Unknown>,
bytes: *const c_void,
length: NSUInteger,
) -> Id<Self, Unknown> {
let this = ManuallyDrop::new(this);
Id::new(msg_send![this, initWithBytes: bytes, length: length])
}
pub unsafe fn initWithBytesNoCopy_length_deallocator_(
this: Id<Self, Unknown>,
bytes: *mut c_void,
length: NSUInteger,
deallocator: *mut c_void,
) -> Id<Self, Unknown> {
let this = ManuallyDrop::new(this);
Id::new(msg_send![
this,
initWithBytesNoCopy: bytes,
length: length,
deallocator: deallocator,
])
}
}
45 changes: 22 additions & 23 deletions objc2-foundation/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -13,35 +13,34 @@ 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 {
self.len() == 0
}

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<Self, Self::Ownership> {
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()
}
}

Expand All @@ -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()
}
}
}
Expand Down

0 comments on commit 3457bd3

Please sign in to comment.