Skip to main content

cidre/cf/
data.rs

1use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
2
3use crate::{arc, cf, define_cf_type};
4
5#[cfg(feature = "ns")]
6use crate::ns;
7
8define_cf_type!(
9    #[doc(alias = "CFDataRef")]
10    Data(cf::Type)
11);
12
13define_cf_type!(
14    #[doc(alias = "CFMutableDataRef")]
15    DataMut(Data)
16);
17
18impl Data {
19    #[doc(alias = "CFDataGetTypeID")]
20    #[inline]
21    pub fn type_id() -> cf::TypeId {
22        unsafe { CFDataGetTypeID() }
23    }
24
25    #[inline]
26    pub fn new_in(
27        bytes: *const u8,
28        length: cf::Index,
29        allocator: Option<&cf::Allocator>,
30    ) -> Option<arc::R<cf::Data>> {
31        unsafe { CFDataCreate(allocator, bytes, length) }
32    }
33
34    #[inline]
35    pub fn new(bytes: *const u8, length: cf::Index) -> Option<arc::R<cf::Data>> {
36        Self::new_in(bytes, length, None)
37    }
38
39    #[inline]
40    pub fn from_slice(slice: &[u8]) -> Option<arc::R<Self>> {
41        Self::new(slice.as_ptr(), slice.len() as _)
42    }
43
44    #[doc(alias = "length")]
45    #[inline]
46    pub fn len(&self) -> usize {
47        unsafe { CFDataGetLength(self) as _ }
48    }
49
50    #[inline]
51    pub fn is_empty(&self) -> bool {
52        self.len() == 0
53    }
54
55    #[inline]
56    pub fn copy_mut_in(
57        &self,
58        capacity: cf::Index,
59        allocator: Option<&cf::Allocator>,
60    ) -> Option<arc::R<DataMut>> {
61        unsafe { CFDataCreateMutableCopy(allocator, capacity, self) }
62    }
63
64    #[inline]
65    pub fn copy_mut(&self, capacity: usize) -> arc::R<DataMut> {
66        unsafe { self.copy_mut_in(capacity as _, None).unwrap_unchecked() }
67    }
68
69    #[inline]
70    pub fn bytes_ptr(&self) -> *const u8 {
71        unsafe { CFDataGetBytePtr(self) }
72    }
73
74    #[inline]
75    pub fn copy_bytes(&self, buffer: &mut [u8]) {
76        unsafe { self.get_bytes(cf::Range::new(0, buffer.len() as _), buffer.as_mut_ptr()) }
77    }
78
79    #[inline]
80    pub unsafe fn get_bytes(&self, range: cf::Range, buffer: *mut u8) {
81        unsafe { CFDataGetBytes(self, range, buffer) }
82    }
83
84    #[inline]
85    pub fn as_slice(&self) -> &[u8] {
86        unsafe { &*slice_from_raw_parts(self.bytes_ptr() as _, self.len()) }
87    }
88
89    #[cfg(feature = "ns")]
90    #[inline]
91    pub fn as_ns(&self) -> &ns::Data {
92        unsafe { std::mem::transmute(self) }
93    }
94}
95
96impl DataMut {
97    #[inline]
98    pub fn new_in(
99        capacity: cf::Index,
100        allocator: Option<&cf::Allocator>,
101    ) -> Option<arc::R<cf::DataMut>> {
102        unsafe { CFDataCreateMutable(allocator, capacity) }
103    }
104
105    #[inline]
106    pub fn with_capacity(capacity: usize) -> arc::R<DataMut> {
107        unsafe { Self::new_in(capacity as _, None).unwrap_unchecked() }
108    }
109
110    /// # Safety
111    ///
112    /// use [`Self::push_bytes`]
113    #[doc(alias = "CFDataAppendBytes")]
114    #[inline]
115    pub unsafe fn append_bytes(&mut self, bytes: *const u8, length: cf::Index) {
116        unsafe { CFDataAppendBytes(self, bytes, length) }
117    }
118
119    #[inline]
120    #[doc(alias = "CFDataAppendBytes")]
121    pub fn push_bytes(&mut self, bytes: &[u8]) {
122        unsafe { self.append_bytes(bytes.as_ptr(), bytes.len() as _) }
123    }
124
125    /// # Safety
126    /// use `as_mut_slice()`
127    #[doc(alias = "CFDataGetMutableBytePtr")]
128    #[inline]
129    pub unsafe fn bytes_ptr_mut(&mut self) -> *mut u8 {
130        unsafe { CFDataGetMutableBytePtr(self) }
131    }
132
133    #[doc(alias = "CFDataSetLength")]
134    #[inline]
135    pub fn set_len(&mut self, len: cf::Index) {
136        unsafe { CFDataSetLength(self, len) }
137    }
138
139    #[inline]
140    pub fn as_mut_slice(&mut self) -> &mut [u8] {
141        unsafe { &mut *slice_from_raw_parts_mut(self.bytes_ptr_mut(), self.len()) }
142    }
143
144    #[cfg(feature = "ns")]
145    #[inline]
146    pub fn as_ns_mut(&mut self) -> &mut ns::DataMut {
147        unsafe { std::mem::transmute(self) }
148    }
149}
150
151/// ```
152/// use cidre::{arc, cf};
153/// let data: arc::R<cf::Data> = arc::R::from(&[1u8][..]);
154/// assert_eq!(data.len(), 1);
155/// data.show();
156/// ```
157impl From<&[u8]> for arc::R<Data> {
158    fn from(bytes: &[u8]) -> Self {
159        unsafe { Data::new(bytes.as_ptr(), bytes.len() as _).unwrap_unchecked() }
160    }
161}
162
163#[link(name = "CoreFoundation", kind = "framework")]
164unsafe extern "C-unwind" {
165    fn CFDataGetTypeID() -> cf::TypeId;
166    fn CFDataCreate(
167        allocator: Option<&cf::Allocator>,
168        bytes: *const u8,
169        length: cf::Index,
170    ) -> Option<arc::R<cf::Data>>;
171    fn CFDataGetLength(data: &Data) -> cf::Index;
172    fn CFDataCreateMutable(
173        allocator: Option<&cf::Allocator>,
174        capacity: cf::Index,
175    ) -> Option<arc::R<cf::DataMut>>;
176    fn CFDataAppendBytes(data: &DataMut, bytes: *const u8, length: cf::Index);
177    fn CFDataCreateMutableCopy(
178        allocator: Option<&cf::Allocator>,
179        capacity: cf::Index,
180        data: &Data,
181    ) -> Option<arc::R<DataMut>>;
182
183    fn CFDataGetBytePtr(data: &cf::Data) -> *const u8;
184    fn CFDataGetBytes(data: &cf::Data, range: cf::Range, buffer: *mut u8);
185
186    fn CFDataGetMutableBytePtr(data: &mut cf::DataMut) -> *mut u8;
187    fn CFDataSetLength(data: &mut cf::DataMut, length: cf::Index);
188}