#![allow(clippy::missing_panics_doc)]
use super::base::{impl_cf_type_wrapper, AsCFType, CFType, SwiftObject};
use super::CFString;
use crate::ffi;
use std::fmt;
impl_cf_type_wrapper!(CFArray, cf_array_get_type_id);
impl_cf_type_wrapper!(CFDictionary, cf_dictionary_get_type_id);
pub type CFDict = CFDictionary;
impl_cf_type_wrapper!(CFBag, cf_bag_get_type_id);
impl_cf_type_wrapper!(CFAttributedString, cf_attributed_string_get_type_id);
impl CFArray {
#[must_use]
pub fn from_values(values: &[&dyn AsCFType]) -> Self {
let raw_values: Vec<*mut std::ffi::c_void> =
values.iter().map(|value| value.as_ptr()).collect();
let ptr = unsafe { ffi::cf_array_create(raw_values.as_ptr(), raw_values.len()) };
Self::from_raw(ptr).expect("CFArrayCreate returned NULL")
}
#[must_use]
pub fn len(&self) -> usize {
unsafe { ffi::cf_array_get_count(self.as_ptr()) }
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn get(&self, index: usize) -> Option<CFType> {
let ptr = unsafe { ffi::cf_array_get_value_at_index(self.as_ptr(), index) };
CFType::from_raw(ptr)
}
#[must_use]
pub fn values(&self) -> Vec<CFType> {
(0..self.len())
.filter_map(|index| self.get(index))
.collect()
}
}
impl CFDictionary {
#[must_use]
pub fn from_pairs(pairs: &[(&dyn AsCFType, &dyn AsCFType)]) -> Self {
let keys: Vec<*mut std::ffi::c_void> = pairs.iter().map(|(key, _)| key.as_ptr()).collect();
let values: Vec<*mut std::ffi::c_void> =
pairs.iter().map(|(_, value)| value.as_ptr()).collect();
let ptr = unsafe { ffi::cf_dictionary_create(keys.as_ptr(), values.as_ptr(), pairs.len()) };
Self::from_raw(ptr).expect("CFDictionaryCreate returned NULL")
}
#[must_use]
pub fn len(&self) -> usize {
unsafe { ffi::cf_dictionary_get_count(self.as_ptr()) }
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn contains_key(&self, key: &dyn AsCFType) -> bool {
unsafe { ffi::cf_dictionary_contains_key(self.as_ptr(), key.as_ptr()) }
}
#[must_use]
pub fn get(&self, key: &dyn AsCFType) -> Option<CFType> {
let ptr = unsafe { ffi::cf_dictionary_get_value(self.as_ptr(), key.as_ptr()) };
CFType::from_raw(ptr)
}
#[must_use]
pub fn keys(&self) -> CFArray {
let ptr = unsafe { ffi::cf_dictionary_copy_keys(self.as_ptr()) };
CFArray::from_raw(ptr).expect("CFDictionary keys array should be non-null")
}
#[must_use]
pub fn values(&self) -> CFArray {
let ptr = unsafe { ffi::cf_dictionary_copy_values(self.as_ptr()) };
CFArray::from_raw(ptr).expect("CFDictionary values array should be non-null")
}
}
impl CFBag {
#[must_use]
pub fn from_values(values: &[&dyn AsCFType]) -> Self {
let raw_values: Vec<*mut std::ffi::c_void> =
values.iter().map(|value| value.as_ptr()).collect();
let ptr = unsafe { ffi::cf_bag_create(raw_values.as_ptr(), raw_values.len()) };
Self::from_raw(ptr).expect("CFBagCreate returned NULL")
}
#[must_use]
pub fn len(&self) -> usize {
unsafe { ffi::cf_bag_get_count(self.as_ptr()) }
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn contains(&self, candidate: &dyn AsCFType) -> bool {
unsafe { ffi::cf_bag_contains_value(self.as_ptr(), candidate.as_ptr()) }
}
#[must_use]
pub fn count_of_value(&self, candidate: &dyn AsCFType) -> usize {
unsafe { ffi::cf_bag_get_count_of_value(self.as_ptr(), candidate.as_ptr()) }
}
}
impl CFAttributedString {
#[must_use]
pub fn new(string: &CFString) -> Self {
let ptr = unsafe { ffi::cf_attributed_string_create(string.as_ptr()) };
Self::from_raw(ptr).expect("CFAttributedStringCreate returned NULL")
}
#[must_use]
pub fn string(&self) -> CFString {
let ptr = unsafe { ffi::cf_attributed_string_get_string(self.as_ptr()) };
CFString::from_raw(ptr).expect("CFAttributedStringGetString returned NULL")
}
#[must_use]
pub fn len(&self) -> usize {
unsafe { ffi::cf_attributed_string_get_length(self.as_ptr()) }
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct CFTree(SwiftObject);
impl CFTree {
#[must_use]
pub fn new(value: Option<&dyn AsCFType>) -> Self {
let ptr =
unsafe { ffi::cf_tree_create(value.map_or(std::ptr::null_mut(), AsCFType::as_ptr)) };
Self(SwiftObject::from_raw(ptr).expect("tree bridge returned NULL"))
}
#[must_use]
pub(crate) fn from_raw(ptr: *mut std::ffi::c_void) -> Option<Self> {
SwiftObject::from_raw(ptr).map(Self)
}
#[must_use]
pub(crate) const fn as_ptr(&self) -> *mut std::ffi::c_void {
self.0.as_ptr()
}
pub fn append_child(&self, child: &Self) {
unsafe { ffi::cf_tree_append_child(self.as_ptr(), child.as_ptr()) };
}
#[must_use]
pub fn child_count(&self) -> usize {
unsafe { ffi::cf_tree_get_child_count(self.as_ptr()) }
}
#[must_use]
pub fn child_at(&self, index: usize) -> Option<Self> {
let ptr = unsafe { ffi::cf_tree_get_child_at_index(self.as_ptr(), index) };
Self::from_raw(ptr)
}
#[must_use]
pub fn value(&self) -> Option<CFType> {
let ptr = unsafe { ffi::cf_tree_copy_value(self.as_ptr()) };
CFType::from_raw(ptr)
}
}
impl fmt::Debug for CFTree {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CFTree")
.field("ptr", &self.as_ptr())
.field("child_count", &self.child_count())
.finish()
}
}