apple_cf/cf/
collections.rs1#![allow(clippy::missing_panics_doc)]
4
5use super::base::{impl_cf_type_wrapper, AsCFType, CFType, SwiftObject};
29use super::CFString;
30use crate::ffi;
31use std::fmt;
32
33impl_cf_type_wrapper!(CFArray, cf_array_get_type_id);
34impl_cf_type_wrapper!(CFDictionary, cf_dictionary_get_type_id);
35pub type CFDict = CFDictionary;
36impl_cf_type_wrapper!(CFBag, cf_bag_get_type_id);
37impl_cf_type_wrapper!(CFAttributedString, cf_attributed_string_get_type_id);
38
39impl CFArray {
40 #[must_use]
42 pub fn from_values(values: &[&dyn AsCFType]) -> Self {
43 let raw_values: Vec<*mut std::ffi::c_void> =
44 values.iter().map(|value| value.as_ptr()).collect();
45 let ptr = unsafe { ffi::cf_array_create(raw_values.as_ptr(), raw_values.len()) };
46 Self::from_raw(ptr).expect("CFArrayCreate returned NULL")
47 }
48
49 #[must_use]
51 pub fn len(&self) -> usize {
52 unsafe { ffi::cf_array_get_count(self.as_ptr()) }
53 }
54
55 #[must_use]
57 pub fn is_empty(&self) -> bool {
58 self.len() == 0
59 }
60
61 #[must_use]
63 pub fn get(&self, index: usize) -> Option<CFType> {
64 let ptr = unsafe { ffi::cf_array_get_value_at_index(self.as_ptr(), index) };
65 CFType::from_raw(ptr)
66 }
67
68 #[must_use]
70 pub fn values(&self) -> Vec<CFType> {
71 (0..self.len())
72 .filter_map(|index| self.get(index))
73 .collect()
74 }
75}
76
77impl CFDictionary {
78 #[must_use]
80 pub fn from_pairs(pairs: &[(&dyn AsCFType, &dyn AsCFType)]) -> Self {
81 let keys: Vec<*mut std::ffi::c_void> = pairs.iter().map(|(key, _)| key.as_ptr()).collect();
82 let values: Vec<*mut std::ffi::c_void> =
83 pairs.iter().map(|(_, value)| value.as_ptr()).collect();
84 let ptr = unsafe { ffi::cf_dictionary_create(keys.as_ptr(), values.as_ptr(), pairs.len()) };
85 Self::from_raw(ptr).expect("CFDictionaryCreate returned NULL")
86 }
87
88 #[must_use]
90 pub fn len(&self) -> usize {
91 unsafe { ffi::cf_dictionary_get_count(self.as_ptr()) }
92 }
93
94 #[must_use]
96 pub fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99
100 #[must_use]
102 pub fn contains_key(&self, key: &dyn AsCFType) -> bool {
103 unsafe { ffi::cf_dictionary_contains_key(self.as_ptr(), key.as_ptr()) }
104 }
105
106 #[must_use]
108 pub fn get(&self, key: &dyn AsCFType) -> Option<CFType> {
109 let ptr = unsafe { ffi::cf_dictionary_get_value(self.as_ptr(), key.as_ptr()) };
110 CFType::from_raw(ptr)
111 }
112
113 #[must_use]
115 pub fn keys(&self) -> CFArray {
116 let ptr = unsafe { ffi::cf_dictionary_copy_keys(self.as_ptr()) };
117 CFArray::from_raw(ptr).expect("CFDictionary keys array should be non-null")
118 }
119
120 #[must_use]
122 pub fn values(&self) -> CFArray {
123 let ptr = unsafe { ffi::cf_dictionary_copy_values(self.as_ptr()) };
124 CFArray::from_raw(ptr).expect("CFDictionary values array should be non-null")
125 }
126}
127
128impl CFBag {
129 #[must_use]
131 pub fn from_values(values: &[&dyn AsCFType]) -> Self {
132 let raw_values: Vec<*mut std::ffi::c_void> =
133 values.iter().map(|value| value.as_ptr()).collect();
134 let ptr = unsafe { ffi::cf_bag_create(raw_values.as_ptr(), raw_values.len()) };
135 Self::from_raw(ptr).expect("CFBagCreate returned NULL")
136 }
137
138 #[must_use]
140 pub fn len(&self) -> usize {
141 unsafe { ffi::cf_bag_get_count(self.as_ptr()) }
142 }
143
144 #[must_use]
146 pub fn is_empty(&self) -> bool {
147 self.len() == 0
148 }
149
150 #[must_use]
152 pub fn contains(&self, candidate: &dyn AsCFType) -> bool {
153 unsafe { ffi::cf_bag_contains_value(self.as_ptr(), candidate.as_ptr()) }
154 }
155
156 #[must_use]
158 pub fn count_of_value(&self, candidate: &dyn AsCFType) -> usize {
159 unsafe { ffi::cf_bag_get_count_of_value(self.as_ptr(), candidate.as_ptr()) }
160 }
161}
162
163impl CFAttributedString {
164 #[must_use]
166 pub fn new(string: &CFString) -> Self {
167 let ptr = unsafe { ffi::cf_attributed_string_create(string.as_ptr()) };
168 Self::from_raw(ptr).expect("CFAttributedStringCreate returned NULL")
169 }
170
171 #[must_use]
173 pub fn string(&self) -> CFString {
174 let ptr = unsafe { ffi::cf_attributed_string_get_string(self.as_ptr()) };
175 CFString::from_raw(ptr).expect("CFAttributedStringGetString returned NULL")
176 }
177
178 #[must_use]
180 pub fn len(&self) -> usize {
181 unsafe { ffi::cf_attributed_string_get_length(self.as_ptr()) }
182 }
183
184 #[must_use]
186 pub fn is_empty(&self) -> bool {
187 self.len() == 0
188 }
189}
190
191#[derive(Clone, PartialEq, Eq, Hash)]
193pub struct CFTree(SwiftObject);
194
195impl CFTree {
196 #[must_use]
198 pub fn new(value: Option<&dyn AsCFType>) -> Self {
199 let ptr =
200 unsafe { ffi::cf_tree_create(value.map_or(std::ptr::null_mut(), AsCFType::as_ptr)) };
201 Self(SwiftObject::from_raw(ptr).expect("tree bridge returned NULL"))
202 }
203
204 #[must_use]
205 pub(crate) fn from_raw(ptr: *mut std::ffi::c_void) -> Option<Self> {
206 SwiftObject::from_raw(ptr).map(Self)
207 }
208
209 #[must_use]
211 pub(crate) const fn as_ptr(&self) -> *mut std::ffi::c_void {
212 self.0.as_ptr()
213 }
214
215 pub fn append_child(&self, child: &Self) {
217 unsafe { ffi::cf_tree_append_child(self.as_ptr(), child.as_ptr()) };
218 }
219
220 #[must_use]
222 pub fn child_count(&self) -> usize {
223 unsafe { ffi::cf_tree_get_child_count(self.as_ptr()) }
224 }
225
226 #[must_use]
228 pub fn child_at(&self, index: usize) -> Option<Self> {
229 let ptr = unsafe { ffi::cf_tree_get_child_at_index(self.as_ptr(), index) };
230 Self::from_raw(ptr)
231 }
232
233 #[must_use]
235 pub fn value(&self) -> Option<CFType> {
236 let ptr = unsafe { ffi::cf_tree_copy_value(self.as_ptr()) };
237 CFType::from_raw(ptr)
238 }
239}
240
241impl fmt::Debug for CFTree {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 f.debug_struct("CFTree")
244 .field("ptr", &self.as_ptr())
245 .field("child_count", &self.child_count())
246 .finish()
247 }
248}