objc_foundation/
data.rs

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        // The bytes pointer may be null for length zero
20        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            // Recreate the Vec and let it drop
44            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        // The bytes pointer may be null for length zero
78        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}