@@ -112,9 +112,129 @@ impl CFDictionary {
112112 TCFType :: wrap_under_get_rule ( value)
113113 }
114114
115+ pub fn get_keys_and_values ( & self ) -> ( Vec < * const c_void > , Vec < * const c_void > ) {
116+ let length = self . len ( ) ;
117+ let mut keys = Vec :: with_capacity ( length) ;
118+ let mut values = Vec :: with_capacity ( length) ;
119+
120+ unsafe {
121+ CFDictionaryGetKeysAndValues ( self . 0 , keys. as_mut_ptr ( ) , values. as_mut_ptr ( ) ) ;
122+ keys. set_len ( length) ;
123+ values. set_len ( length) ;
124+ }
125+
126+ ( keys, values)
127+ }
128+ }
129+
130+ /// An mutable dictionary of key-value pairs.
131+ pub struct CFMutableDictionary ( CFMutableDictionaryRef ) ;
132+
133+ impl Drop for CFMutableDictionary {
134+ fn drop ( & mut self ) {
135+ unsafe {
136+ CFRelease ( self . as_CFTypeRef ( ) )
137+ }
138+ }
139+ }
140+
141+ impl_TCFType ! ( CFMutableDictionary , CFMutableDictionaryRef , CFDictionaryGetTypeID ) ;
142+ impl_CFTypeDescription ! ( CFMutableDictionary ) ;
143+
144+ impl CFMutableDictionary {
145+ pub fn new ( ) -> Self {
146+ Self :: with_capacity ( 0 )
147+ }
148+
149+ pub fn with_capacity ( capacity : isize ) -> Self {
150+ unsafe {
151+ let dictionary_ref = CFDictionaryCreateMutable ( kCFAllocatorDefault,
152+ capacity as _ ,
153+ & kCFTypeDictionaryKeyCallBacks,
154+ & kCFTypeDictionaryValueCallBacks) ;
155+ TCFType :: wrap_under_create_rule ( dictionary_ref)
156+ }
157+ }
158+
159+ pub fn copy_with_capacity ( & self , capacity : isize ) -> Self {
160+ unsafe {
161+ let dictionary_ref = CFDictionaryCreateMutableCopy ( kCFAllocatorDefault, capacity as _ , self . 0 ) ;
162+ TCFType :: wrap_under_get_rule ( dictionary_ref)
163+ }
164+ }
165+
166+ pub fn from_CFType_pairs < R1 , R2 , K , V > ( pairs : & [ ( K , V ) ] ) -> CFMutableDictionary
167+ where K : TCFType < R1 > , V : TCFType < R2 > {
168+ let result = Self :: with_capacity ( pairs. len ( ) as _ ) ;
169+ unsafe {
170+ for & ( ref key, ref value) in pairs {
171+ result. add ( key. as_CFTypeRef ( ) , value. as_CFTypeRef ( ) ) ;
172+ }
173+ }
174+ result
175+ }
176+
177+ // Immutable interface
178+
115179 #[ inline]
116- pub unsafe fn set_value ( & self , key : * const c_void , value : * const c_void ) {
117- CFDictionarySetValue ( self . 0 , key, value)
180+ pub fn len ( & self ) -> usize {
181+ unsafe {
182+ CFDictionaryGetCount ( self . 0 ) as usize
183+ }
184+ }
185+
186+ #[ inline]
187+ pub fn is_empty ( & self ) -> bool {
188+ self . len ( ) == 0
189+ }
190+
191+ #[ inline]
192+ pub fn contains_key ( & self , key : * const c_void ) -> bool {
193+ unsafe {
194+ CFDictionaryContainsKey ( self . 0 , key) != 0
195+ }
196+ }
197+
198+ /// Similar to `contains_key` but acts on a higher level, automatically converting from any
199+ /// `TCFType` to the raw pointer of its concrete TypeRef.
200+ #[ inline]
201+ pub fn contains_key2 < X , K : TCFType < * const X > > ( & self , key : & K ) -> bool {
202+ self . contains_key ( key. as_concrete_TypeRef ( ) as * const c_void )
203+ }
204+
205+ #[ inline]
206+ pub fn find ( & self , key : * const c_void ) -> Option < * const c_void > {
207+ unsafe {
208+ let mut value: * const c_void = ptr:: null ( ) ;
209+ if CFDictionaryGetValueIfPresent ( self . 0 , key, & mut value) != 0 {
210+ Some ( value)
211+ } else {
212+ None
213+ }
214+ }
215+ }
216+
217+ /// Similar to `find` but acts on a higher level, automatically converting from any `TCFType`
218+ /// to the raw pointer of its concrete TypeRef.
219+ #[ inline]
220+ pub fn find2 < X , K : TCFType < * const X > > ( & self , key : & K ) -> Option < * const c_void > {
221+ self . find ( key. as_concrete_TypeRef ( ) as * const c_void )
222+ }
223+
224+ /// # Panics
225+ ///
226+ /// Panics if the key is not present in the dictionary. Use `find` to get an `Option` instead
227+ /// of panicking.
228+ #[ inline]
229+ pub fn get ( & self , key : * const c_void ) -> * const c_void {
230+ self . find ( key) . expect ( & format ! ( "No entry found for key {:p}" , key) )
231+ }
232+
233+ /// A convenience function to retrieve `CFType` instances.
234+ #[ inline]
235+ pub unsafe fn get_CFType ( & self , key : * const c_void ) -> CFType {
236+ let value: CFTypeRef = mem:: transmute ( self . get ( key) ) ;
237+ TCFType :: wrap_under_get_rule ( value)
118238 }
119239
120240 pub fn get_keys_and_values ( & self ) -> ( Vec < * const c_void > , Vec < * const c_void > ) {
@@ -130,4 +250,81 @@ impl CFDictionary {
130250
131251 ( keys, values)
132252 }
253+
254+ // Mutable interface
255+
256+ /// Adds the key-value pair to the dictionary if no such key already exist.
257+ #[ inline]
258+ pub unsafe fn add ( & self , key : * const c_void , value : * const c_void ) {
259+ CFDictionaryAddValue ( self . 0 , key, value)
260+ }
261+
262+ /// Similar to `add` but acts on a higher level, automatically converting from any `TCFType`
263+ /// to the raw pointer of its concrete TypeRef.
264+ #[ inline]
265+ pub fn add2 < RK , RV , K , V > ( & self , key : & K , value : & V )
266+ where K : TCFType < * const RK > ,
267+ V : TCFType < * const RV > {
268+ unsafe {
269+ self . add ( key. as_concrete_TypeRef ( ) as * const _ ,
270+ value. as_concrete_TypeRef ( ) as * const _ )
271+ }
272+ }
273+
274+ /// Sets the value of the key in the dictionary.
275+ #[ inline]
276+ pub unsafe fn set ( & self , key : * const c_void , value : * const c_void ) {
277+ CFDictionarySetValue ( self . 0 , key, value)
278+ }
279+
280+ /// Similar to `set` but acts on a higher level, automatically converting from any `TCFType`
281+ /// to the raw pointer of its concrete TypeRef.
282+ #[ inline]
283+ pub fn set2 < RK , RV , K , V > ( & self , key : & K , value : & V )
284+ where K : TCFType < * const RK > ,
285+ V : TCFType < * const RV > {
286+ unsafe {
287+ self . set ( key. as_concrete_TypeRef ( ) as * const c_void ,
288+ value. as_concrete_TypeRef ( ) as * const c_void )
289+ }
290+ }
291+
292+ /// Replaces the value of the key in the dictionary.
293+ #[ inline]
294+ pub unsafe fn replace ( & self , key : * const c_void , value : * const c_void ) {
295+ CFDictionaryReplaceValue ( self . 0 , key, value)
296+ }
297+
298+ /// Similar to `replace` but acts on a higher level, automatically converting from any `TCFType`
299+ /// to the raw pointer of its concrete TypeRef.
300+ #[ inline]
301+ pub fn replace2 < RK , RV , K , V > ( & self , key : & K , value : & V )
302+ where K : TCFType < * const RK > ,
303+ V : TCFType < * const RV > {
304+ unsafe {
305+ self . replace ( key. as_concrete_TypeRef ( ) as * const c_void ,
306+ value. as_concrete_TypeRef ( ) as * const c_void )
307+ }
308+ }
309+
310+ /// Removes the value of the key from the dictionary.
311+ #[ inline]
312+ pub unsafe fn remove ( & self , key : * const c_void ) {
313+ CFDictionaryRemoveValue ( self . 0 , key) ;
314+ }
315+
316+ /// Similar to `remove` but acts on a higher level, automatically converting from any `TCFType`
317+ /// to the raw pointer of its concrete TypeRef.
318+ #[ inline]
319+ pub fn remove2 < RK , K > ( & self , key : & K )
320+ where K : TCFType < * const RK > {
321+ unsafe {
322+ self . remove ( key. as_concrete_TypeRef ( ) as * const c_void )
323+ }
324+ }
325+
326+ #[ inline]
327+ pub fn remove_all ( & self ) {
328+ unsafe { CFDictionaryRemoveAllValues ( self . 0 ) }
329+ }
133330}
0 commit comments