use core_foundation::base::{CFType, ToVoid};
use core_foundation::boolean::{CFBoolean, CFBooleanGetTypeID};
use core_foundation::dictionary::{CFDictionary, CFDictionaryGetTypeID, CFDictionaryRef};
use core_foundation::number::{CFNumber, CFNumberGetTypeID};
use core_foundation::string::{CFString, CFStringGetTypeID};
pub use core_foundation::base::TCFType;
use crate::{Error, Result};
pub trait DictionaryProps {
fn get_dict(&self, raw_key: &'static str) -> Result<CFDictionary<CFString, CFType>>;
fn get_bool(&self, raw_key: &'static str) -> Result<bool>;
fn get_i64(&self, raw_key: &'static str) -> Result<i64>;
fn get_string(&self, raw_key: &'static str) -> Result<String>;
}
impl DictionaryProps for CFDictionary<CFString, CFType> {
fn get_dict(&self, raw_key: &'static str) -> Result<CFDictionary<CFString, CFType>> {
let key = CFString::from_static_string(raw_key);
self.find(&key)
.and_then(|value_ref| {
unsafe {
debug_assert!(value_ref.type_of() == CFDictionaryGetTypeID());
}
let ptr = value_ref.to_void() as CFDictionaryRef;
unsafe { Some(CFDictionary::wrap_under_get_rule(ptr)) }
})
.ok_or_else(|| Error::missing_entity(raw_key))
}
fn get_bool(&self, raw_key: &'static str) -> Result<bool> {
let key = CFString::from_static_string(raw_key);
self.find(&key)
.and_then(|value_ref| {
unsafe {
debug_assert!(value_ref.type_of() == CFBooleanGetTypeID());
}
value_ref.downcast::<CFBoolean>()
})
.map(Into::into)
.ok_or_else(|| Error::missing_entity(raw_key))
}
fn get_i64(&self, raw_key: &'static str) -> Result<i64> {
let key = CFString::from_static_string(raw_key);
self.find(&key)
.and_then(|value_ref| {
unsafe {
debug_assert!(value_ref.type_of() == CFNumberGetTypeID());
}
value_ref.downcast::<CFNumber>()
})
.and_then(|number| number.to_i64())
.ok_or_else(|| Error::missing_entity(raw_key))
}
fn get_string(&self, raw_key: &'static str) -> Result<String> {
let key = CFString::from_static_string(raw_key);
self.find(&key)
.and_then(|value_ref| {
unsafe {
debug_assert!(value_ref.type_of() == CFStringGetTypeID());
}
value_ref.downcast::<CFString>()
})
.map(|cf_string| cf_string.to_string())
.ok_or_else(|| Error::missing_entity(raw_key))
}
}