1use alloc::vec::Vec;
2use core::ffi::c_void;
3use core::fmt;
4use core::marker::PhantomData;
5#[cfg(feature = "NSRange")]
6use core::ops::Range;
7use core::panic::{RefUnwindSafe, UnwindSafe};
8use core::ptr::NonNull;
9use core::slice::{self};
10
11use objc2::rc::Retained;
12#[cfg(feature = "block2")]
13use objc2::rc::RetainedFromIterator;
14use objc2::{extern_methods, AnyThread};
15
16use crate::{NSData, NSMutableData};
17
18impl UnwindSafe for NSData {}
19impl RefUnwindSafe for NSData {}
20
21impl NSData {
24 extern_methods!(
25 #[unsafe(method(bytes))]
26 pub(crate) fn bytes_raw(&self) -> *const c_void;
27 );
28}
29
30impl NSMutableData {
31 extern_methods!(
32 #[unsafe(method(mutableBytes))]
33 pub(crate) fn mutable_bytes_raw(&self) -> *mut c_void;
34 );
35}
36
37impl NSData {
38 pub fn with_bytes(bytes: &[u8]) -> Retained<Self> {
40 let bytes_ptr = bytes.as_ptr() as *mut c_void;
41 unsafe { Self::initWithBytes_length(Self::alloc(), bytes_ptr, bytes.len()) }
42 }
43
44 #[cfg(feature = "block2")]
45 #[cfg(feature = "alloc")]
46 pub fn from_vec(bytes: Vec<u8>) -> Retained<Self> {
47 unsafe { with_vec(Self::alloc(), bytes) }
48 }
49}
50
51impl NSMutableData {
52 pub fn with_bytes(bytes: &[u8]) -> Retained<Self> {
53 let bytes_ptr = bytes.as_ptr() as *mut c_void;
54 unsafe { Self::initWithBytes_length(Self::alloc(), bytes_ptr, bytes.len()) }
56 }
57
58 #[cfg(feature = "block2")]
59 pub fn from_vec(bytes: Vec<u8>) -> Retained<Self> {
60 unsafe { with_vec(Self::alloc(), bytes) }
62 }
63}
64
65impl NSData {
66 pub fn len(&self) -> usize {
67 self.length()
68 }
69
70 pub fn is_empty(&self) -> bool {
71 self.len() == 0
72 }
73
74 pub unsafe fn as_bytes_unchecked(&self) -> &[u8] {
84 let ptr = self.bytes_raw();
85 if !ptr.is_null() {
86 let ptr: *const u8 = ptr.cast();
87 unsafe { slice::from_raw_parts(ptr, self.len()) }
101 } else {
102 &[]
104 }
105 }
106
107 pub fn to_vec(&self) -> Vec<u8> {
109 let mut vec = Vec::with_capacity(self.len());
114 vec.extend_from_slice(unsafe { self.as_bytes_unchecked() });
117 vec
118 }
119
120 pub fn iter(&self) -> Iter<'_> {
122 Iter::new(self)
123 }
124}
125
126impl NSMutableData {
127 #[doc(alias = "mutableBytes")]
134 #[allow(clippy::mut_from_ref)]
135 pub unsafe fn as_mut_bytes_unchecked(&self) -> &mut [u8] {
136 let ptr = self.mutable_bytes_raw();
137 if !ptr.is_null() {
140 let ptr: *mut u8 = ptr.cast();
141 unsafe { slice::from_raw_parts_mut(ptr, self.len()) }
145 } else {
146 &mut []
147 }
148 }
149
150 #[doc(alias = "appendBytes:length:")]
151 pub fn extend_from_slice(&self, bytes: &[u8]) {
152 let bytes_ptr: NonNull<c_void> = NonNull::new(bytes.as_ptr() as *mut u8).unwrap().cast();
153 unsafe { self.appendBytes_length(bytes_ptr, bytes.len()) }
154 }
155
156 pub fn push(&self, byte: u8) {
157 self.extend_from_slice(&[byte]);
158 }
159
160 #[doc(alias = "replaceBytesInRange:withBytes:length:")]
161 #[cfg(feature = "NSRange")]
162 pub fn replace_range(&self, range: Range<usize>, bytes: &[u8]) {
163 let ptr = bytes.as_ptr().cast();
166 unsafe { self.replaceBytesInRange_withBytes_length(range.into(), ptr, bytes.len()) }
167 }
168
169 #[cfg(feature = "NSRange")]
170 pub fn set_bytes(&self, bytes: &[u8]) {
171 let len = self.len();
172 self.replace_range(0..len, bytes);
173 }
174}
175
176impl fmt::Debug for NSData {
177 #[inline]
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.debug_list().entries(self.iter()).finish()
181 }
182}
183
184#[derive(Debug, Clone)]
197pub struct Iter<'a> {
198 p: PhantomData<&'a NSData>,
199 #[cfg(debug_assertions)]
200 data: &'a NSData,
201 #[cfg(debug_assertions)]
202 length: usize,
203 bytes: alloc::vec::IntoIter<u8>,
204}
205
206impl<'a> Iter<'a> {
207 fn new(data: &'a NSData) -> Self {
208 Self {
209 p: PhantomData,
210 #[cfg(debug_assertions)]
211 data,
212 #[cfg(debug_assertions)]
213 length: data.length(),
214 bytes: data.to_vec().into_iter(),
215 }
216 }
217}
218
219impl ExactSizeIterator for Iter<'_> {
220 fn len(&self) -> usize {
221 self.bytes.len()
222 }
223}
224
225impl Iterator for Iter<'_> {
226 type Item = u8;
227
228 fn next(&mut self) -> Option<Self::Item> {
229 #[cfg(debug_assertions)]
230 {
231 if self.length != self.data.length() {
232 panic!("NSData was mutated while iterating");
233 }
234 }
235
236 self.bytes.next()
237 }
238
239 fn size_hint(&self) -> (usize, Option<usize>) {
240 let len = self.len();
241 (len, Some(len))
242 }
243}
244
245impl core::iter::FusedIterator for Iter<'_> {}
253
254impl<'a> IntoIterator for &'a NSData {
255 type Item = u8;
256 type IntoIter = Iter<'a>;
257
258 fn into_iter(self) -> Self::IntoIter {
259 Iter::new(self)
260 }
261}
262
263impl<'a> IntoIterator for &'a NSMutableData {
264 type Item = u8;
265 type IntoIter = Iter<'a>;
266
267 fn into_iter(self) -> Self::IntoIter {
268 Iter::new(self)
269 }
270}
271
272impl Extend<u8> for &NSMutableData {
273 fn extend<T: IntoIterator<Item = u8>>(&mut self, iter: T) {
278 let iterator = iter.into_iter();
279 iterator.for_each(move |item| self.push(item));
280 }
281}
282
283impl<'a> Extend<&'a u8> for &NSMutableData {
285 fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
286 let iterator = iter.into_iter();
287 iterator.for_each(move |item| self.push(*item));
288 }
289}
290
291#[cfg(feature = "std")]
292impl std::io::Write for &NSMutableData {
293 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
294 self.extend_from_slice(buf);
295 Ok(buf.len())
296 }
297
298 fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
299 self.extend_from_slice(buf);
300 Ok(())
301 }
302
303 fn flush(&mut self) -> std::io::Result<()> {
304 Ok(())
305 }
306}
307
308#[cfg(feature = "block2")]
309impl RetainedFromIterator<u8> for NSData {
310 fn retained_from_iter<I: IntoIterator<Item = u8>>(iter: I) -> Retained<Self> {
311 let vec = Vec::from_iter(iter);
312 Self::from_vec(vec)
313 }
314}
315
316#[cfg(feature = "block2")]
317impl RetainedFromIterator<u8> for NSMutableData {
318 fn retained_from_iter<I: IntoIterator<Item = u8>>(iter: I) -> Retained<Self> {
319 let vec = Vec::from_iter(iter);
320 Self::from_vec(vec)
321 }
322}
323
324#[cfg(feature = "block2")]
325#[cfg(feature = "alloc")]
326unsafe fn with_vec<T: objc2::Message>(obj: objc2::rc::Allocated<T>, bytes: Vec<u8>) -> Retained<T> {
327 use core::mem::ManuallyDrop;
328
329 use block2::{DynBlock, RcBlock};
330
331 let capacity = bytes.capacity();
332
333 let dealloc = RcBlock::new(move |bytes: *mut c_void, len: usize| {
334 let _ = unsafe { <Vec<u8>>::from_raw_parts(bytes.cast(), len, capacity) };
336 });
337 let dealloc: &DynBlock<dyn Fn(*mut c_void, usize) + 'static> = &dealloc;
338
339 let mut bytes = ManuallyDrop::new(bytes);
340 let len = bytes.len();
343 let bytes_ptr: *mut c_void = bytes.as_mut_ptr().cast();
344
345 unsafe {
346 objc2::msg_send![
347 obj,
348 initWithBytesNoCopy: bytes_ptr,
349 length: len,
350 deallocator: dealloc,
351 ]
352 }
353}