3
3
use alloc:: vec:: Vec ;
4
4
use core:: fmt;
5
5
use core:: ops:: Index ;
6
+ #[ cfg( feature = "Foundation_NSMutableData" ) ]
7
+ use core:: ops:: { IndexMut , Range } ;
6
8
use core:: panic:: { RefUnwindSafe , UnwindSafe } ;
7
9
use core:: slice:: { self , SliceIndex } ;
8
10
9
11
use crate :: common:: * ;
12
+ #[ cfg( feature = "Foundation_NSMutableData" ) ]
13
+ use crate :: Foundation :: NSMutableData ;
10
14
use crate :: Foundation :: { self , NSData } ;
11
15
12
16
// SAFETY: `NSData` is immutable and `NSMutableData` can only be mutated from
@@ -17,7 +21,6 @@ unsafe impl Send for NSData {}
17
21
impl UnwindSafe for NSData { }
18
22
impl RefUnwindSafe for NSData { }
19
23
20
- /// Creation methods.
21
24
impl NSData {
22
25
pub fn with_bytes ( bytes : & [ u8 ] ) -> Id < Self > {
23
26
let bytes_ptr = bytes. as_ptr ( ) as * mut c_void ;
@@ -34,15 +37,29 @@ impl NSData {
34
37
//
35
38
// NSMutableData does not have this problem.
36
39
#[ cfg( feature = "gnustep-1-7" ) ]
37
- let cls = objc2:: class!( NSDataWithDeallocatorBlock ) ;
40
+ let obj = unsafe { objc2:: msg_send_id! [ objc2 :: class!( NSDataWithDeallocatorBlock ) , alloc ] } ;
38
41
#[ cfg( not( feature = "gnustep-1-7" ) ) ]
39
- let cls = Self :: class ( ) ;
42
+ let obj = Self :: alloc ( ) ;
40
43
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) }
42
60
}
43
61
}
44
62
45
- /// Accessor methods.
46
63
impl NSData {
47
64
pub fn len ( & self ) -> usize {
48
65
self . length ( )
@@ -53,15 +70,54 @@ impl NSData {
53
70
}
54
71
55
72
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
60
80
& [ ]
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 ( ) ) }
61
94
} else {
62
- unsafe { slice :: from_raw_parts ( ptr , self . len ( ) ) }
95
+ & mut [ ]
63
96
}
64
97
}
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
+ }
65
121
}
66
122
67
123
impl AsRef < [ u8 ] > for NSData {
@@ -70,6 +126,20 @@ impl AsRef<[u8]> for NSData {
70
126
}
71
127
}
72
128
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
+
73
143
// Note: We don't implement `Borrow<[u8]>` since we can't guarantee that `Eq`,
74
144
// `Ord` and `Hash` are equal for `NSData` vs. `[u8]`!
75
145
@@ -83,6 +153,24 @@ impl<I: SliceIndex<[u8]>> Index<I> for NSData {
83
153
}
84
154
}
85
155
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
+
86
174
impl fmt:: Debug for NSData {
87
175
#[ inline]
88
176
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
@@ -100,12 +188,82 @@ impl<'a> IntoIterator for &'a NSData {
100
188
}
101
189
}
102
190
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
+
103
262
#[ 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 > {
105
264
use core:: mem:: ManuallyDrop ;
106
265
107
266
use block2:: { Block , ConcreteBlock } ;
108
- use objc2:: msg_send_id;
109
267
110
268
let capacity = bytes. capacity ( ) ;
111
269
@@ -120,8 +278,8 @@ pub(crate) unsafe fn with_vec(cls: &Class, bytes: Vec<u8>) -> Id<Object> {
120
278
let bytes_ptr: * mut c_void = bytes. as_mut_ptr ( ) . cast ( ) ;
121
279
122
280
unsafe {
123
- msg_send_id ! [
124
- msg_send_id! [ cls , alloc ] ,
281
+ objc2 :: msg_send_id![
282
+ obj ,
125
283
initWithBytesNoCopy: bytes_ptr,
126
284
length: bytes. len( ) ,
127
285
deallocator: dealloc,
0 commit comments