1use std::mem;
2use std::ops::Range;
3use std::os::raw::c_void;
4use std::slice;
5
6use objc_id::Id;
7use block::{Block, ConcreteBlock};
8use {INSObject, INSCopying, INSMutableCopying, NSRange};
9
10pub trait INSData : INSObject {
11 fn len(&self) -> usize {
12 unsafe {
13 msg_send![self, length]
14 }
15 }
16
17 fn bytes(&self) -> &[u8] {
18 let ptr: *const c_void = unsafe { msg_send![self, bytes] };
19 let (ptr, len) = if ptr.is_null() {
21 (0x1 as *const u8, 0)
22 } else {
23 (ptr as *const u8, self.len())
24 };
25 unsafe {
26 slice::from_raw_parts(ptr, len)
27 }
28 }
29
30 fn with_bytes(bytes: &[u8]) -> Id<Self> {
31 let cls = Self::class();
32 unsafe {
33 let obj: *mut Self = msg_send![cls, alloc];
34 let obj: *mut Self = msg_send![obj, initWithBytes:bytes.as_ptr()
35 length:bytes.len()];
36 Id::from_retained_ptr(obj)
37 }
38 }
39
40 fn from_vec(bytes: Vec<u8>) -> Id<Self> {
41 let capacity = bytes.capacity();
42 let dealloc = ConcreteBlock::new(move |bytes: *mut c_void, len: usize| unsafe {
43 let _ = Vec::from_raw_parts(bytes as *mut u8, len, capacity);
45 });
46 let dealloc = dealloc.copy();
47 let dealloc: &Block<(*mut c_void, usize), ()> = &dealloc;
48
49 let mut bytes = bytes;
50 let cls = Self::class();
51 unsafe {
52 let obj: *mut Self = msg_send![cls, alloc];
53 let obj: *mut Self = msg_send![obj, initWithBytesNoCopy:bytes.as_mut_ptr()
54 length:bytes.len()
55 deallocator:dealloc];
56 mem::forget(bytes);
57 Id::from_retained_ptr(obj)
58 }
59 }
60}
61
62object_struct!(NSData);
63
64impl INSData for NSData { }
65
66impl INSCopying for NSData {
67 type Output = NSData;
68}
69
70impl INSMutableCopying for NSData {
71 type Output = NSMutableData;
72}
73
74pub trait INSMutableData : INSData {
75 fn bytes_mut(&mut self) -> &mut [u8] {
76 let ptr: *mut c_void = unsafe { msg_send![self, mutableBytes] };
77 let (ptr, len) = if ptr.is_null() {
79 (0x1 as *mut u8, 0)
80 } else {
81 (ptr as *mut u8, self.len())
82 };
83 unsafe {
84 slice::from_raw_parts_mut(ptr, len)
85 }
86 }
87
88 fn set_len(&mut self, len: usize) {
89 unsafe {
90 let _: () = msg_send![self, setLength:len];
91 }
92 }
93
94 fn append(&mut self, bytes: &[u8]) {
95 unsafe {
96 let _: () = msg_send![self, appendBytes:bytes.as_ptr()
97 length:bytes.len()];
98 }
99 }
100
101 fn replace_range(&mut self, range: Range<usize>, bytes: &[u8]) {
102 let range = NSRange::from_range(range);
103 unsafe {
104 let _: () = msg_send![self, replaceBytesInRange:range
105 withBytes:bytes.as_ptr()
106 length:bytes.len()];
107 }
108 }
109
110 fn set_bytes(&mut self, bytes: &[u8]) {
111 let len = self.len();
112 self.replace_range(0..len, bytes);
113 }
114}
115
116object_struct!(NSMutableData);
117
118impl INSData for NSMutableData { }
119
120impl INSMutableData for NSMutableData { }
121
122impl INSCopying for NSMutableData {
123 type Output = NSData;
124}
125
126impl INSMutableCopying for NSMutableData {
127 type Output = NSMutableData;
128}
129
130#[cfg(test)]
131mod tests {
132 use INSObject;
133 use super::{INSData, INSMutableData, NSData, NSMutableData};
134
135 #[test]
136 fn test_bytes() {
137 let bytes = [3, 7, 16, 52, 112, 19];
138 let data = NSData::with_bytes(&bytes);
139 assert!(data.len() == bytes.len());
140 assert!(data.bytes() == bytes);
141 }
142
143 #[test]
144 fn test_no_bytes() {
145 let data = NSData::new();
146 assert!(Some(data.bytes()).is_some());
147 }
148
149 #[test]
150 fn test_bytes_mut() {
151 let mut data = NSMutableData::with_bytes(&[7, 16]);
152 data.bytes_mut()[0] = 3;
153 assert!(data.bytes() == [3, 16]);
154 }
155
156 #[test]
157 fn test_set_len() {
158 let mut data = NSMutableData::with_bytes(&[7, 16]);
159 data.set_len(4);
160 assert!(data.len() == 4);
161 assert!(data.bytes() == [7, 16, 0, 0]);
162
163 data.set_len(1);
164 assert!(data.len() == 1);
165 assert!(data.bytes() == [7]);
166 }
167
168 #[test]
169 fn test_append() {
170 let mut data = NSMutableData::with_bytes(&[7, 16]);
171 data.append(&[3, 52]);
172 assert!(data.len() == 4);
173 assert!(data.bytes() == [7, 16, 3, 52]);
174 }
175
176 #[test]
177 fn test_replace() {
178 let mut data = NSMutableData::with_bytes(&[7, 16]);
179 data.replace_range(0..0, &[3]);
180 assert!(data.bytes() == [3, 7, 16]);
181
182 data.replace_range(1..2, &[52, 13]);
183 assert!(data.bytes() == [3, 52, 13, 16]);
184
185 data.replace_range(2..4, &[6]);
186 assert!(data.bytes() == [3, 52, 6]);
187
188 data.set_bytes(&[8, 17]);
189 assert!(data.bytes() == [8, 17]);
190 }
191
192 #[test]
193 fn test_from_vec() {
194 let bytes = vec![3, 7, 16];
195 let bytes_ptr = bytes.as_ptr();
196
197 let data = NSData::from_vec(bytes);
198 assert!(data.bytes().as_ptr() == bytes_ptr);
199 }
200}