Skip to content

Commit b9c86ad

Browse files
committed
Use NSMutableData::from_vec in tests
NSData::from_vec is broken in GNUStep, see gnustep/libs-base#213
1 parent 8577599 commit b9c86ad

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

objc2_foundation/src/data.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ use core::{ffi::c_void, ptr::NonNull};
77
use super::{INSCopying, INSMutableCopying, INSObject, NSRange};
88
use objc2::msg_send;
99
use objc2::rc::{Id, Owned};
10-
#[cfg(feature = "block")]
11-
use objc2_block::{Block, ConcreteBlock};
1210

1311
pub trait INSData: INSObject {
1412
fn len(&self) -> usize {
@@ -22,12 +20,11 @@ pub trait INSData: INSObject {
2220
fn bytes(&self) -> &[u8] {
2321
let ptr: *const c_void = unsafe { msg_send![self, bytes] };
2422
// The bytes pointer may be null for length zero
25-
let (ptr, len) = if ptr.is_null() {
26-
(0x1 as *const u8, 0)
23+
if ptr.is_null() {
24+
&[]
2725
} else {
28-
(ptr as *const u8, self.len())
29-
};
30-
unsafe { slice::from_raw_parts(ptr, len) }
26+
unsafe { slice::from_raw_parts(ptr as *const u8, self.len()) }
27+
}
3128
}
3229

3330
fn with_bytes(bytes: &[u8]) -> Id<Self, Owned> {
@@ -46,6 +43,8 @@ pub trait INSData: INSObject {
4643

4744
#[cfg(feature = "block")]
4845
fn from_vec(bytes: Vec<u8>) -> Id<Self, Owned> {
46+
use objc2_block::{Block, ConcreteBlock};
47+
4948
let capacity = bytes.capacity();
5049
let dealloc = ConcreteBlock::new(move |bytes: *mut c_void, len: usize| unsafe {
5150
// Recreate the Vec and let it drop
@@ -56,6 +55,23 @@ pub trait INSData: INSObject {
5655

5756
let mut bytes = bytes;
5857
let bytes_ptr = bytes.as_mut_ptr() as *mut c_void;
58+
59+
// GNUStep's NSData `initWithBytesNoCopy:length:deallocator:` has a
60+
// bug; it forgets to assign the input buffer and length to the
61+
// instance before it swizzles to NSDataWithDeallocatorBlock.
62+
// See https://github.com/gnustep/libs-base/pull/213
63+
// So we just use NSDataWithDeallocatorBlock directly.
64+
// TODO
65+
// #[cfg(feature = "gnustep")]
66+
// let cls = {
67+
// let cls = Self::class();
68+
// if cls == class!(NSData) {
69+
// class!(NSDataWithDeallocatorBlock)
70+
// } else {
71+
// cls
72+
// }
73+
// };
74+
// #[cfg(not(feature = "gnustep"))]
5975
let cls = Self::class();
6076
unsafe {
6177
let obj: *mut Self = msg_send![cls, alloc];
@@ -215,7 +231,8 @@ mod tests {
215231
let bytes = vec![3, 7, 16];
216232
let bytes_ptr = bytes.as_ptr();
217233

218-
let data = NSData::from_vec(bytes);
219-
assert!(data.bytes().as_ptr() == bytes_ptr);
234+
// This functionality on NSData is broken on GNUStep
235+
let data = NSMutableData::from_vec(bytes);
236+
assert_eq!(data.bytes().as_ptr(), bytes_ptr);
220237
}
221238
}

0 commit comments

Comments
 (0)