From 1dd66bd610a20f1734d3cdb2a194dd40360dd200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 19 Oct 2018 10:26:58 +0200 Subject: [PATCH 1/6] Add conversion from CFDictionary to CFMutableDictionary --- core-foundation/src/dictionary.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core-foundation/src/dictionary.rs b/core-foundation/src/dictionary.rs index 10b9158..ca0e277 100644 --- a/core-foundation/src/dictionary.rs +++ b/core-foundation/src/dictionary.rs @@ -235,6 +235,17 @@ impl CFMutableDictionary { } } +impl<'a, K, V> From<&'a CFDictionary> for CFMutableDictionary { + /// Creates a new mutable dictionary with the key-value pairs from another dictionary. + /// The capacity of the new mutable dictionary is not limited. + fn from(dict: &'a CFDictionary) -> Self { + unsafe { + let mut_dict_ref = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dict.0); + TCFType::wrap_under_create_rule(mut_dict_ref) + } + } +} + #[cfg(test)] pub mod test { @@ -313,4 +324,21 @@ pub mod test { assert_eq!(value, CFBoolean::true_value()); assert_eq!(dict.find(&invalid_key), None); } + + #[test] + fn convert_immutable_to_mutable_dict() { + let dict: CFDictionary = CFDictionary::from_CFType_pairs(&[ + (CFString::from_static_string("Foo"), CFBoolean::true_value()), + ]); + let mut mut_dict = CFMutableDictionary::from(&dict); + assert_eq!(dict.retain_count(), 1); + assert_eq!(mut_dict.retain_count(), 1); + + assert_eq!(mut_dict.len(), 1); + assert_eq!(*mut_dict.get(&CFString::from_static_string("Foo")), CFBoolean::true_value()); + + mut_dict.add(&CFString::from_static_string("Bar"), &CFBoolean::false_value()); + assert_eq!(dict.len(), 1); + assert_eq!(mut_dict.len(), 2); + } } From 8ca27465894c2a46cb5f553c41b00b2ff2feaff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 23 Oct 2018 09:38:35 +0200 Subject: [PATCH 2/6] Implement ConcreteCFType for CFDictionary<*void, *void> --- core-foundation/src/dictionary.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core-foundation/src/dictionary.rs b/core-foundation/src/dictionary.rs index ca0e277..5b3faf5 100644 --- a/core-foundation/src/dictionary.rs +++ b/core-foundation/src/dictionary.rs @@ -19,6 +19,7 @@ use std::marker::PhantomData; use base::{ItemRef, FromVoid, ToVoid}; use base::{CFIndexConvertible, TCFType}; +use ConcreteCFType; // consume the type parameters with PhantomDatas pub struct CFDictionary(CFDictionaryRef, PhantomData, PhantomData); @@ -32,6 +33,8 @@ impl Drop for CFDictionary { impl_TCFType!(CFDictionary, CFDictionaryRef, CFDictionaryGetTypeID); impl_CFTypeDescription!(CFDictionary); +unsafe impl ConcreteCFType for CFDictionary<*const c_void, *const c_void> {} + impl CFDictionary { pub fn from_CFType_pairs(pairs: &[(K, V)]) -> CFDictionary where K: TCFType, V: TCFType { let (keys, values): (Vec, Vec) = pairs From 57170cf8384bb5ba3a500d5021bd0d75476dfc1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Thu, 18 Oct 2018 15:45:47 +0200 Subject: [PATCH 3/6] Allow converting dictionaries to their untyped counterparts --- core-foundation/src/dictionary.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core-foundation/src/dictionary.rs b/core-foundation/src/dictionary.rs index 5b3faf5..36e46c5 100644 --- a/core-foundation/src/dictionary.rs +++ b/core-foundation/src/dictionary.rs @@ -53,6 +53,20 @@ impl CFDictionary { } } + #[inline] + pub fn to_untyped(&self) -> CFDictionary { + unsafe { CFDictionary::wrap_under_get_rule(self.0) } + } + + /// Returns the same dictionary, but with the types reset to void pointers. + /// Equal to `to_untyped`, but is faster since it does not increment the retain count. + #[inline] + pub fn into_untyped(self) -> CFDictionary { + let reference = self.0; + mem::forget(self); + unsafe { CFDictionary::wrap_under_create_rule(reference) } + } + #[inline] pub fn len(&self) -> usize { unsafe { @@ -149,6 +163,20 @@ impl CFMutableDictionary { result } + #[inline] + pub fn to_untyped(&self) -> CFMutableDictionary { + unsafe { CFMutableDictionary::wrap_under_get_rule(self.0) } + } + + /// Returns the same dictionary, but with the types reset to void pointers. + /// Equal to `to_untyped`, but is faster since it does not increment the retain count. + #[inline] + pub fn into_untyped(self) -> CFMutableDictionary { + let reference = self.0; + mem::forget(self); + unsafe { CFMutableDictionary::wrap_under_create_rule(reference) } + } + // Immutable interface #[inline] From f8c0f59a48da02afddd293b9266fd66ad12a714c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Thu, 18 Oct 2018 16:13:57 +0200 Subject: [PATCH 4/6] Add as_immutable to CFMutableDictionary --- core-foundation/src/dictionary.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/core-foundation/src/dictionary.rs b/core-foundation/src/dictionary.rs index 36e46c5..45f64a4 100644 --- a/core-foundation/src/dictionary.rs +++ b/core-foundation/src/dictionary.rs @@ -177,6 +177,12 @@ impl CFMutableDictionary { unsafe { CFMutableDictionary::wrap_under_create_rule(reference) } } + /// Borrow self as an immutable dictionary. + #[inline] + pub fn as_immutable(&self) -> ItemRef> { + unsafe { CFDictionary::from_void(self.0 as _) } + } + // Immutable interface #[inline] @@ -372,4 +378,19 @@ pub mod test { assert_eq!(dict.len(), 1); assert_eq!(mut_dict.len(), 2); } + + #[test] + fn mutable_dictionary_as_immutable() { + let mut mut_dict: CFMutableDictionary = CFMutableDictionary::new(); + mut_dict.add(&CFString::from_static_string("Bar"), &CFBoolean::false_value()); + assert_eq!(mut_dict.retain_count(), 1); + + let dict = mut_dict.as_immutable(); + assert_eq!(mut_dict.retain_count(), 1); + assert_eq!(dict.retain_count(), 1); + assert_eq!(*dict.get(&CFString::from_static_string("Bar")), CFBoolean::false_value()); + + mem::drop(dict); + assert_eq!(mut_dict.retain_count(), 1); + } } From c539fbc64423e389dcc53a8a70098c178873ebea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 19 Oct 2018 11:21:59 +0200 Subject: [PATCH 5/6] Fix indentation --- core-foundation/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core-foundation/src/lib.rs b/core-foundation/src/lib.rs index 814c240..d1c88aa 100644 --- a/core-foundation/src/lib.rs +++ b/core-foundation/src/lib.rs @@ -97,21 +97,21 @@ macro_rules! impl_TCFType { unsafe impl<'a> $crate::base::ToVoid<$ty> for &'a $ty { fn to_void(&self) -> *const ::std::os::raw::c_void { - use $crate::base::TCFTypeRef; + use $crate::base::TCFTypeRef; self.as_concrete_TypeRef().as_void_ptr() } } unsafe impl $crate::base::ToVoid<$ty> for $ty { fn to_void(&self) -> *const ::std::os::raw::c_void { - use $crate::base::TCFTypeRef; + use $crate::base::TCFTypeRef; self.as_concrete_TypeRef().as_void_ptr() } } unsafe impl $crate::base::ToVoid<$ty> for $ty_ref { fn to_void(&self) -> *const ::std::os::raw::c_void { - use $crate::base::TCFTypeRef; + use $crate::base::TCFTypeRef; self.as_void_ptr() } } From 1cb7f0816f26674ddea63836be41e1921845364c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Mon, 22 Oct 2018 16:02:55 +0200 Subject: [PATCH 6/6] Change as_immutable to to_immutable --- core-foundation/src/dictionary.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core-foundation/src/dictionary.rs b/core-foundation/src/dictionary.rs index 45f64a4..5b808c3 100644 --- a/core-foundation/src/dictionary.rs +++ b/core-foundation/src/dictionary.rs @@ -177,10 +177,10 @@ impl CFMutableDictionary { unsafe { CFMutableDictionary::wrap_under_create_rule(reference) } } - /// Borrow self as an immutable dictionary. + /// Returns a `CFDictionary` pointing to the same underlying dictionary as this mutable one. #[inline] - pub fn as_immutable(&self) -> ItemRef> { - unsafe { CFDictionary::from_void(self.0 as _) } + pub fn to_immutable(&self) -> CFDictionary { + unsafe { CFDictionary::wrap_under_get_rule(self.0) } } // Immutable interface @@ -385,9 +385,9 @@ pub mod test { mut_dict.add(&CFString::from_static_string("Bar"), &CFBoolean::false_value()); assert_eq!(mut_dict.retain_count(), 1); - let dict = mut_dict.as_immutable(); - assert_eq!(mut_dict.retain_count(), 1); - assert_eq!(dict.retain_count(), 1); + let dict = mut_dict.to_immutable(); + assert_eq!(mut_dict.retain_count(), 2); + assert_eq!(dict.retain_count(), 2); assert_eq!(*dict.get(&CFString::from_static_string("Bar")), CFBoolean::false_value()); mem::drop(dict);