From 1c47d8fa7fd2826993bafcbd6e7c103cb3475575 Mon Sep 17 00:00:00 2001 From: Christian Howe Date: Sun, 1 Jan 2017 20:45:18 -0500 Subject: [PATCH 1/2] Add CFDictionary function to get keys and values --- core-foundation-sys/src/dictionary.rs | 4 ++++ core-foundation/src/dictionary.rs | 14 ++++++++++++++ core-foundation/src/lib.rs | 7 ++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/core-foundation-sys/src/dictionary.rs b/core-foundation-sys/src/dictionary.rs index d9aa8d9..bf51bb1 100644 --- a/core-foundation-sys/src/dictionary.rs +++ b/core-foundation-sys/src/dictionary.rs @@ -72,4 +72,8 @@ extern { pub fn CFDictionarySetValue(theDict: CFMutableDictionaryRef, key: *const c_void, value: *const c_void); + pub fn CFDictionaryGetKeysAndValues(theDict: CFDictionaryRef, + keys: *mut *const c_void, + values: *mut *const c_void); + } diff --git a/core-foundation/src/dictionary.rs b/core-foundation/src/dictionary.rs index e27ed4a..9953c4b 100644 --- a/core-foundation/src/dictionary.rs +++ b/core-foundation/src/dictionary.rs @@ -101,4 +101,18 @@ impl CFDictionary { pub unsafe fn set_value(&self, key: *const c_void, value: *const c_void) { CFDictionarySetValue(self.0, key, value) } + + pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) { + let length = self.len(); + let mut keys = Vec::with_capacity(length); + let mut values = Vec::with_capacity(length); + + unsafe { + CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr()); + keys.set_len(length); + values.set_len(length); + } + + (keys, values) + } } diff --git a/core-foundation/src/lib.rs b/core-foundation/src/lib.rs index 345b123..0a0e328 100644 --- a/core-foundation/src/lib.rs +++ b/core-foundation/src/lib.rs @@ -83,10 +83,15 @@ pub mod test { let tru = CFBoolean::true_value(); let n42 = number(42); - let _d = CFDictionary::from_CFType_pairs(&[ + let d = CFDictionary::from_CFType_pairs(&[ (bar.as_CFType(), boo.as_CFType()), (baz.as_CFType(), tru.as_CFType()), (foo.as_CFType(), n42.as_CFType()), ]); + + let (v1, v2) = d.get_keys_and_values(); + + assert!(v1 == &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]); + assert!(v2 == &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]); } } From 66aba074c1007959f86f5d64c3da201840ad478f Mon Sep 17 00:00:00 2001 From: Christian Howe Date: Sun, 1 Jan 2017 19:38:22 -0500 Subject: [PATCH 2/2] Add CFPropertyList serialization --- core-foundation-sys/src/base.rs | 1 + core-foundation-sys/src/lib.rs | 1 + core-foundation-sys/src/propertylist.rs | 37 +++++++++++ core-foundation/src/lib.rs | 1 + core-foundation/src/propertylist.rs | 86 +++++++++++++++++++++++++ 5 files changed, 126 insertions(+) create mode 100644 core-foundation-sys/src/propertylist.rs create mode 100644 core-foundation/src/propertylist.rs diff --git a/core-foundation-sys/src/base.rs b/core-foundation-sys/src/base.rs index 6cf8cb6..5f29cd5 100644 --- a/core-foundation-sys/src/base.rs +++ b/core-foundation-sys/src/base.rs @@ -61,6 +61,7 @@ extern { //fn CFCopyTypeIDDescription //fn CFEqual //fn CFGetAllocator + pub fn CFEqual(cf1: CFTypeRef, cf2: CFTypeRef) -> Boolean; pub fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex; pub fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID; pub fn CFHash(cf: CFTypeRef) -> CFHashCode; diff --git a/core-foundation-sys/src/lib.rs b/core-foundation-sys/src/lib.rs index 2574689..b39da97 100644 --- a/core-foundation-sys/src/lib.rs +++ b/core-foundation-sys/src/lib.rs @@ -19,6 +19,7 @@ pub mod dictionary; pub mod error; pub mod messageport; pub mod number; +pub mod propertylist; pub mod runloop; pub mod set; pub mod string; diff --git a/core-foundation-sys/src/propertylist.rs b/core-foundation-sys/src/propertylist.rs new file mode 100644 index 0000000..2396ef9 --- /dev/null +++ b/core-foundation-sys/src/propertylist.rs @@ -0,0 +1,37 @@ +use base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeRef}; +use data::CFDataRef; +use error::CFErrorRef; + +pub type CFPropertyListRef = CFTypeRef; + +pub type CFPropertyListFormat = CFIndex; +pub const kCFPropertyListOpenStepFormat: CFPropertyListFormat = 1; +pub const kCFPropertyListXMLFormat_v1_0: CFPropertyListFormat = 100; +pub const kCFPropertyListBinaryFormat_v1_0: CFPropertyListFormat = 200; + +pub type CFPropertyListMutabilityOptions = CFOptionFlags; +pub const kCFPropertyListImmutable: CFPropertyListMutabilityOptions = 0; +pub const kCFPropertyListMutableContainers: CFPropertyListMutabilityOptions = 1; +pub const kCFPropertyListMutableContainersAndLeaves: CFPropertyListMutabilityOptions = 2; + +extern "C" { + // CFPropertyList.h + // + + // fn CFPropertyListCreateDeepCopy + // fn CFPropertyListIsValid + pub fn CFPropertyListCreateWithData(allocator: CFAllocatorRef, + data: CFDataRef, + options: CFPropertyListMutabilityOptions, + format: *mut CFPropertyListFormat, + error: *mut CFErrorRef) + -> CFPropertyListRef; + // fn CFPropertyListCreateWithStream + // fn CFPropertyListWrite + pub fn CFPropertyListCreateData(allocator: CFAllocatorRef, + propertyList: CFPropertyListRef, + format: CFPropertyListFormat, + options: CFOptionFlags, + error: *mut CFErrorRef) + -> CFDataRef; +} diff --git a/core-foundation/src/lib.rs b/core-foundation/src/lib.rs index 0a0e328..f4ca71d 100644 --- a/core-foundation/src/lib.rs +++ b/core-foundation/src/lib.rs @@ -60,6 +60,7 @@ pub mod set; pub mod string; pub mod url; pub mod bundle; +pub mod propertylist; pub mod runloop; #[cfg(test)] diff --git a/core-foundation/src/propertylist.rs b/core-foundation/src/propertylist.rs new file mode 100644 index 0000000..01d43e1 --- /dev/null +++ b/core-foundation/src/propertylist.rs @@ -0,0 +1,86 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Core Foundation property lists + +use std::ptr; + +use error::CFError; +use data::CFData; +use base::{CFType, TCFType}; + +pub use core_foundation_sys::propertylist::*; +use core_foundation_sys::error::CFErrorRef; +use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault}; + +pub fn create_with_data(data: CFData, + options: CFPropertyListMutabilityOptions) + -> Result<(CFType, CFPropertyListFormat), CFError> { + unsafe { + let mut error: CFErrorRef = ptr::null_mut(); + let mut format: CFPropertyListFormat = 0; + let property_list = CFPropertyListCreateWithData(kCFAllocatorDefault, + data.as_concrete_TypeRef(), + options, + &mut format as *mut CFPropertyListFormat, + &mut error as *mut CFErrorRef); + if property_list.is_null() { + Err(TCFType::wrap_under_create_rule(error)) + } else { + Ok((TCFType::wrap_under_create_rule(property_list), format)) + } + } +} + +pub fn create_data(property_list: CFType, format: CFPropertyListFormat) -> Result { + unsafe { + let mut error: CFErrorRef = ptr::null_mut(); + let property_list_ref: CFTypeRef = property_list.as_CFTypeRef(); + let data_ref = CFPropertyListCreateData(kCFAllocatorDefault, + property_list_ref, + format, + 0, + &mut error as *mut CFErrorRef); + if data_ref.is_null() { + Err(TCFType::wrap_under_create_rule(error)) + } else { + Ok(TCFType::wrap_under_create_rule(data_ref)) + } + } +} + +#[cfg(test)] +pub mod test { + #[test] + fn test_property_list_serialization() { + use base::{TCFType, CFEqual}; + use boolean::CFBoolean; + use number::number; + use dictionary::CFDictionary; + use string::CFString; + use super::*; + + let bar = CFString::from_static_string("Bar"); + let baz = CFString::from_static_string("Baz"); + let boo = CFString::from_static_string("Boo"); + let foo = CFString::from_static_string("Foo"); + let tru = CFBoolean::true_value(); + let n42 = number(42); + + let dict1 = CFDictionary::from_CFType_pairs(&[(bar.as_CFType(), boo.as_CFType()), + (baz.as_CFType(), tru.as_CFType()), + (foo.as_CFType(), n42.as_CFType())]); + + let data = create_data(dict1.as_CFType(), kCFPropertyListXMLFormat_v1_0).unwrap(); + let (dict2, _) = create_with_data(data, kCFPropertyListImmutable).unwrap(); + unsafe { + assert!(CFEqual(dict1.as_CFTypeRef(), dict2.as_CFTypeRef()) == 1); + } + } +}