use std::{ffi::c_void, marker::PhantomData};
use crate::{UIErrorKind, UIResult};
use super::{CFArrayRef, CFSerializable, CFType};
pub type CFDictionaryRef = *const c_void;
#[derive(Debug, Clone)]
pub(crate) struct CFDictionary<K> {
pub(crate) inner: CFType,
_key: PhantomData<K>,
}
impl<K> CFDictionary<K>
where K: CFSerializable {
pub fn from_get(reference: CFDictionaryRef) -> UIResult<Self> {
let Some(inner) = CFType::from_get(reference) else {
return Err(UIErrorKind::AllocationFailed { resource: "CFDictionary" }.into());
};
Ok(Self {
inner,
_key: PhantomData,
})
}
#[allow(unused)]
pub fn from_create(reference: CFDictionaryRef) -> UIResult<Self> {
let Some(inner) = CFType::from_create(reference) else {
return Err(UIErrorKind::AllocationFailed { resource: "CFDictionary" }.into());
};
Ok(Self {
inner,
_key: PhantomData,
})
}
pub fn get<V: CFSerializable>(&self, key: &K) -> Option<V> {
let key = key.to_ptr();
if key.is_null() {
return None;
}
let value = unsafe { CFDictionaryGetValue(self.inner.ptr(), key) };
if value.is_null() {
return None;
}
Some(V::from_ptr(value))
}
}
impl<K> CFSerializable for CFDictionary<K> {
fn from_ptr(ptr: *const c_void) -> Self {
Self {
inner: CFType::from_get(ptr).unwrap(),
_key: PhantomData,
}
}
fn to_ptr(&self) -> *const c_void {
self.inner.ptr()
}
}
extern "C-unwind" {
pub(super) fn CFDictionaryGetValue(array: CFArrayRef, key: *const c_void) -> *const c_void;
}