Skip to content

Commit f37bb84

Browse files
authored
Merge pull request #446 from madsmtm/refactor-mutable
Refactor `icrate` mutable counterpart files
2 parents de14f52 + 5d78a92 commit f37bb84

File tree

16 files changed

+1115
-1123
lines changed

16 files changed

+1115
-1123
lines changed

crates/icrate/src/Foundation/additions/array.rs

Lines changed: 276 additions & 92 deletions
Large diffs are not rendered by default.

crates/icrate/src/Foundation/additions/attributed_string.rs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,45 @@ unsafe impl Send for NSAttributedString {}
1515
impl UnwindSafe for NSAttributedString {}
1616
impl RefUnwindSafe for NSAttributedString {}
1717

18-
extern_methods!(
19-
/// Creating attributed strings.
20-
unsafe impl NSAttributedString {
21-
/// Creates a new attributed string from the given string and attributes.
22-
///
23-
/// The attributes are associated with every UTF-16 code unit in the
24-
/// string.
25-
///
26-
/// # Safety
27-
///
28-
/// The attributes must be valid.
29-
#[doc(alias = "initWithString:")]
30-
#[cfg(feature = "Foundation_NSDictionary")]
31-
#[cfg(feature = "Foundation_NSString")]
32-
pub unsafe fn new_with_attributes(
33-
string: &Foundation::NSString,
34-
attributes: &Foundation::NSDictionary<NSAttributedStringKey, Object>,
35-
) -> Id<Self> {
36-
unsafe { Self::initWithString_attributes(Self::alloc(), string, Some(attributes)) }
37-
}
38-
39-
/// Creates a new attributed string without any attributes.
40-
#[doc(alias = "initWithString:")]
41-
#[cfg(feature = "Foundation_NSString")]
42-
pub fn from_nsstring(string: &Foundation::NSString) -> Id<Self> {
43-
Self::initWithString(Self::alloc(), string)
44-
}
18+
impl NSAttributedString {
19+
/// Creates a new attributed string from the given string and attributes.
20+
///
21+
/// The attributes are associated with every UTF-16 code unit in the
22+
/// string.
23+
///
24+
/// # Safety
25+
///
26+
/// The attributes must be valid.
27+
#[doc(alias = "initWithString:")]
28+
#[cfg(feature = "Foundation_NSDictionary")]
29+
#[cfg(feature = "Foundation_NSString")]
30+
pub unsafe fn new_with_attributes(
31+
string: &Foundation::NSString,
32+
attributes: &Foundation::NSDictionary<NSAttributedStringKey, Object>,
33+
) -> Id<Self> {
34+
unsafe { Self::initWithString_attributes(Self::alloc(), string, Some(attributes)) }
4535
}
46-
);
36+
37+
/// Creates a new attributed string without any attributes.
38+
#[doc(alias = "initWithString:")]
39+
#[cfg(feature = "Foundation_NSString")]
40+
pub fn from_nsstring(string: &Foundation::NSString) -> Id<Self> {
41+
Self::initWithString(Self::alloc(), string)
42+
}
43+
}
44+
45+
#[cfg(feature = "Foundation_NSMutableAttributedString")]
46+
impl Foundation::NSMutableAttributedString {
47+
// TODO: new_with_attributes
48+
49+
#[doc(alias = "initWithString:")]
50+
#[cfg(feature = "Foundation_NSString")]
51+
pub fn from_nsstring(string: &Foundation::NSString) -> Id<Self> {
52+
Self::initWithString(Self::alloc(), string)
53+
}
54+
55+
#[doc(alias = "initWithAttributedString:")]
56+
pub fn from_attributed_nsstring(attributed_string: &NSAttributedString) -> Id<Self> {
57+
Self::initWithAttributedString(Self::alloc(), attributed_string)
58+
}
59+
}

crates/icrate/src/Foundation/additions/data.rs

Lines changed: 172 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
use alloc::vec::Vec;
44
use core::fmt;
55
use core::ops::Index;
6+
#[cfg(feature = "Foundation_NSMutableData")]
7+
use core::ops::{IndexMut, Range};
68
use core::panic::{RefUnwindSafe, UnwindSafe};
79
use core::slice::{self, SliceIndex};
810

911
use crate::common::*;
12+
#[cfg(feature = "Foundation_NSMutableData")]
13+
use crate::Foundation::NSMutableData;
1014
use crate::Foundation::{self, NSData};
1115

1216
// SAFETY: `NSData` is immutable and `NSMutableData` can only be mutated from
@@ -17,7 +21,6 @@ unsafe impl Send for NSData {}
1721
impl UnwindSafe for NSData {}
1822
impl RefUnwindSafe for NSData {}
1923

20-
/// Creation methods.
2124
impl NSData {
2225
pub fn with_bytes(bytes: &[u8]) -> Id<Self> {
2326
let bytes_ptr = bytes.as_ptr() as *mut c_void;
@@ -34,15 +37,29 @@ impl NSData {
3437
//
3538
// NSMutableData does not have this problem.
3639
#[cfg(feature = "gnustep-1-7")]
37-
let cls = objc2::class!(NSDataWithDeallocatorBlock);
40+
let obj = unsafe { objc2::msg_send_id![objc2::class!(NSDataWithDeallocatorBlock), alloc] };
3841
#[cfg(not(feature = "gnustep-1-7"))]
39-
let cls = Self::class();
42+
let obj = Self::alloc();
4043

41-
unsafe { Id::cast(with_vec(cls, bytes)) }
44+
unsafe { with_vec(obj, bytes) }
45+
}
46+
}
47+
48+
#[cfg(feature = "Foundation_NSMutableData")]
49+
impl NSMutableData {
50+
pub fn with_bytes(bytes: &[u8]) -> Id<Self> {
51+
let bytes_ptr = bytes.as_ptr() as *mut c_void;
52+
// SAFETY: Same as `NSData::with_bytes`
53+
unsafe { Self::initWithBytes_length(Self::alloc(), bytes_ptr, bytes.len()) }
54+
}
55+
56+
#[cfg(feature = "block")]
57+
pub fn from_vec(bytes: Vec<u8>) -> Id<Self> {
58+
// SAFETY: Same as `NSData::from_vec`
59+
unsafe { with_vec(Self::alloc(), bytes) }
4260
}
4361
}
4462

45-
/// Accessor methods.
4663
impl NSData {
4764
pub fn len(&self) -> usize {
4865
self.length()
@@ -53,15 +70,54 @@ impl NSData {
5370
}
5471

5572
pub fn bytes(&self) -> &[u8] {
56-
let ptr = self.bytes_raw();
57-
let ptr: *const u8 = ptr.cast();
58-
// The bytes pointer may be null for length zero
59-
if ptr.is_null() {
73+
if let Some(ptr) = self.bytes_raw() {
74+
let ptr: *const u8 = ptr.as_ptr().cast();
75+
// SAFETY: The pointer is checked to not be NULL, and since we're
76+
// working with raw bytes (`u8`), the alignment is also correct.
77+
unsafe { slice::from_raw_parts(ptr, self.len()) }
78+
} else {
79+
// The bytes pointer may be null for length zero on GNUStep
6080
&[]
81+
}
82+
}
83+
}
84+
85+
#[cfg(feature = "Foundation_NSMutableData")]
86+
impl NSMutableData {
87+
#[doc(alias = "mutableBytes")]
88+
pub fn bytes_mut(&mut self) -> &mut [u8] {
89+
if let Some(ptr) = self.mutable_bytes_raw() {
90+
let ptr: *mut u8 = ptr.as_ptr().cast();
91+
// SAFETY: Same as `NSData::bytes`, with the addition that a
92+
// mutable slice is safe, since we take `&mut NSMutableData`.
93+
unsafe { slice::from_raw_parts_mut(ptr, self.len()) }
6194
} else {
62-
unsafe { slice::from_raw_parts(ptr, self.len()) }
95+
&mut []
6396
}
6497
}
98+
99+
#[doc(alias = "appendBytes:length:")]
100+
pub fn extend_from_slice(&mut self, bytes: &[u8]) {
101+
let bytes_ptr: NonNull<c_void> = NonNull::new(bytes.as_ptr() as *mut u8).unwrap().cast();
102+
unsafe { self.appendBytes_length(bytes_ptr, bytes.len()) }
103+
}
104+
105+
pub fn push(&mut self, byte: u8) {
106+
self.extend_from_slice(&[byte])
107+
}
108+
109+
#[doc(alias = "replaceBytesInRange:withBytes:length:")]
110+
pub fn replace_range(&mut self, range: Range<usize>, bytes: &[u8]) {
111+
// No need to verify the length of the range here,
112+
// `replaceBytesInRange:` just zero-fills if out of bounds.
113+
let ptr = bytes.as_ptr() as *mut c_void;
114+
unsafe { self.replaceBytesInRange_withBytes_length(range.into(), ptr, bytes.len()) }
115+
}
116+
117+
pub fn set_bytes(&mut self, bytes: &[u8]) {
118+
let len = self.len();
119+
self.replace_range(0..len, bytes);
120+
}
65121
}
66122

67123
impl AsRef<[u8]> for NSData {
@@ -70,6 +126,20 @@ impl AsRef<[u8]> for NSData {
70126
}
71127
}
72128

129+
#[cfg(feature = "Foundation_NSMutableData")]
130+
impl AsRef<[u8]> for NSMutableData {
131+
fn as_ref(&self) -> &[u8] {
132+
self.bytes()
133+
}
134+
}
135+
136+
#[cfg(feature = "Foundation_NSMutableData")]
137+
impl AsMut<[u8]> for NSMutableData {
138+
fn as_mut(&mut self) -> &mut [u8] {
139+
self.bytes_mut()
140+
}
141+
}
142+
73143
// Note: We don't implement `Borrow<[u8]>` since we can't guarantee that `Eq`,
74144
// `Ord` and `Hash` are equal for `NSData` vs. `[u8]`!
75145

@@ -83,6 +153,24 @@ impl<I: SliceIndex<[u8]>> Index<I> for NSData {
83153
}
84154
}
85155

156+
#[cfg(feature = "Foundation_NSMutableData")]
157+
impl<I: SliceIndex<[u8]>> Index<I> for NSMutableData {
158+
type Output = I::Output;
159+
160+
#[inline]
161+
fn index(&self, index: I) -> &Self::Output {
162+
Index::index(self.bytes(), index)
163+
}
164+
}
165+
166+
#[cfg(feature = "Foundation_NSMutableData")]
167+
impl<I: SliceIndex<[u8]>> IndexMut<I> for NSMutableData {
168+
#[inline]
169+
fn index_mut(&mut self, index: I) -> &mut Self::Output {
170+
IndexMut::index_mut(self.bytes_mut(), index)
171+
}
172+
}
173+
86174
impl fmt::Debug for NSData {
87175
#[inline]
88176
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -100,12 +188,82 @@ impl<'a> IntoIterator for &'a NSData {
100188
}
101189
}
102190

191+
#[cfg(feature = "Foundation_NSMutableData")]
192+
impl<'a> IntoIterator for &'a NSMutableData {
193+
type Item = &'a u8;
194+
type IntoIter = core::slice::Iter<'a, u8>;
195+
196+
fn into_iter(self) -> Self::IntoIter {
197+
self.bytes().iter()
198+
}
199+
}
200+
201+
#[cfg(feature = "Foundation_NSMutableData")]
202+
impl<'a> IntoIterator for &'a mut NSMutableData {
203+
type Item = &'a mut u8;
204+
type IntoIter = core::slice::IterMut<'a, u8>;
205+
206+
fn into_iter(self) -> Self::IntoIter {
207+
self.bytes_mut().iter_mut()
208+
}
209+
}
210+
211+
#[cfg(feature = "Foundation_NSMutableData")]
212+
impl Extend<u8> for NSMutableData {
213+
/// You should use [`extend_from_slice`] whenever possible, it is more
214+
/// performant.
215+
///
216+
/// [`extend_from_slice`]: Self::extend_from_slice
217+
fn extend<T: IntoIterator<Item = u8>>(&mut self, iter: T) {
218+
let iterator = iter.into_iter();
219+
iterator.for_each(move |item| self.push(item));
220+
}
221+
}
222+
223+
// Vec also has this impl
224+
#[cfg(feature = "Foundation_NSMutableData")]
225+
impl<'a> Extend<&'a u8> for NSMutableData {
226+
fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
227+
let iterator = iter.into_iter();
228+
iterator.for_each(move |item| self.push(*item));
229+
}
230+
}
231+
232+
#[cfg(feature = "Foundation_NSMutableData")]
233+
impl std::io::Write for NSMutableData {
234+
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
235+
self.extend_from_slice(buf);
236+
Ok(buf.len())
237+
}
238+
239+
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
240+
self.extend_from_slice(buf);
241+
Ok(())
242+
}
243+
244+
fn flush(&mut self) -> std::io::Result<()> {
245+
Ok(())
246+
}
247+
}
248+
249+
// #[cfg(feature = "Foundation_NSMutableData")]
250+
// impl FromIterator<u8> for Id<NSMutableData> {
251+
// fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
252+
// let iter = iter.into_iter();
253+
// let (lower, _) = iter.size_hint();
254+
// let data = Self::with_capacity(lower);
255+
// for item in iter {
256+
// data.push(item);
257+
// }
258+
// data
259+
// }
260+
// }
261+
103262
#[cfg(feature = "block")]
104-
pub(crate) unsafe fn with_vec(cls: &Class, bytes: Vec<u8>) -> Id<Object> {
263+
unsafe fn with_vec<T: Message>(obj: Option<Allocated<T>>, bytes: Vec<u8>) -> Id<T> {
105264
use core::mem::ManuallyDrop;
106265

107266
use block2::{Block, ConcreteBlock};
108-
use objc2::msg_send_id;
109267

110268
let capacity = bytes.capacity();
111269

@@ -120,8 +278,8 @@ pub(crate) unsafe fn with_vec(cls: &Class, bytes: Vec<u8>) -> Id<Object> {
120278
let bytes_ptr: *mut c_void = bytes.as_mut_ptr().cast();
121279

122280
unsafe {
123-
msg_send_id![
124-
msg_send_id![cls, alloc],
281+
objc2::msg_send_id![
282+
obj,
125283
initWithBytesNoCopy: bytes_ptr,
126284
length: bytes.len(),
127285
deallocator: dealloc,

0 commit comments

Comments
 (0)