#![allow(clippy::missing_panics_doc)]
use super::base::{impl_cf_type_wrapper, AsCFType, CFType};
use super::{CFDate, CFNumber, CFString, CFUUID};
use crate::ffi;
use std::ffi::CString;
fn to_cstring(value: &str) -> CString {
CString::new(value).expect("Core Foundation strings may not contain interior NUL bytes")
}
impl_cf_type_wrapper!(CFURL, cf_url_get_type_id);
impl_cf_type_wrapper!(CFBundle, cf_bundle_get_type_id);
impl_cf_type_wrapper!(CFLocale, cf_locale_get_type_id);
impl_cf_type_wrapper!(CFCalendar, cf_calendar_get_type_id);
impl_cf_type_wrapper!(CFTimeZone, cf_time_zone_get_type_id);
impl_cf_type_wrapper!(CFCharacterSet, cf_character_set_get_type_id);
impl_cf_type_wrapper!(CFNumberFormatter, cf_number_formatter_get_type_id);
impl_cf_type_wrapper!(CFDateFormatter, cf_date_formatter_get_type_id);
impl_cf_type_wrapper!(CFFileSecurity, cf_file_security_get_type_id);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum CFNumberFormatterStyle {
NoStyle = 0,
Decimal = 1,
Currency = 2,
Percent = 3,
Scientific = 4,
SpellOut = 5,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum CFDateFormatterStyle {
NoStyle = 0,
Short = 1,
Medium = 2,
Long = 3,
Full = 4,
}
impl CFURL {
#[must_use]
pub fn from_string(value: &str) -> Self {
let value = to_cstring(value);
let ptr = unsafe { ffi::cf_url_create_with_string(value.as_ptr()) };
Self::from_raw(ptr).expect("CFURLCreateWithString returned NULL")
}
#[must_use]
pub fn from_file_system_path(path: &str, is_directory: bool) -> Self {
let path = to_cstring(path);
let ptr = unsafe { ffi::cf_url_create_file_path(path.as_ptr(), is_directory) };
Self::from_raw(ptr).expect("CFURLCreateWithFileSystemPath returned NULL")
}
#[must_use]
pub fn absolute_string(&self) -> CFString {
let ptr = unsafe { ffi::cf_url_copy_absolute_string(self.as_ptr()) };
CFString::from_raw(ptr).expect("CFURLCopyAbsoluteString returned NULL")
}
#[must_use]
pub fn file_system_path(&self) -> CFString {
let ptr = unsafe { ffi::cf_url_copy_file_system_path(self.as_ptr()) };
CFString::from_raw(ptr).expect("CFURLCopyFileSystemPath returned NULL")
}
#[must_use]
pub fn has_directory_path(&self) -> bool {
unsafe { ffi::cf_url_has_directory_path(self.as_ptr()) }
}
}
impl CFBundle {
#[must_use]
pub fn main() -> Option<Self> {
let ptr = unsafe { ffi::cf_bundle_get_main() };
Self::from_raw(ptr)
}
#[must_use]
pub fn from_url(url: &CFURL) -> Option<Self> {
let ptr = unsafe { ffi::cf_bundle_create(url.as_ptr()) };
Self::from_raw(ptr)
}
#[must_use]
pub fn identifier(&self) -> Option<CFString> {
let ptr = unsafe { ffi::cf_bundle_copy_identifier(self.as_ptr()) };
CFString::from_raw(ptr)
}
#[must_use]
pub fn bundle_url(&self) -> CFURL {
let ptr = unsafe { ffi::cf_bundle_copy_bundle_url(self.as_ptr()) };
CFURL::from_raw(ptr).expect("CFBundleCopyBundleURL returned NULL")
}
#[must_use]
pub fn resource_url(
&self,
name: &str,
extension: Option<&str>,
subdir: Option<&str>,
) -> Option<CFURL> {
let name = to_cstring(name);
let extension = extension.map(to_cstring);
let subdir = subdir.map(to_cstring);
let ptr = unsafe {
ffi::cf_bundle_copy_resource_url(
self.as_ptr(),
name.as_ptr(),
extension.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
subdir.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
)
};
CFURL::from_raw(ptr)
}
}
impl CFLocale {
#[must_use]
pub fn current() -> Self {
let ptr = unsafe { ffi::cf_locale_copy_current() };
Self::from_raw(ptr).expect("CFLocaleCopyCurrent returned NULL")
}
#[must_use]
pub fn new(identifier: &str) -> Self {
let identifier = to_cstring(identifier);
let ptr = unsafe { ffi::cf_locale_create(identifier.as_ptr()) };
Self::from_raw(ptr).expect("CFLocaleCreate returned NULL")
}
#[must_use]
pub fn identifier(&self) -> CFString {
let ptr = unsafe { ffi::cf_locale_copy_identifier(self.as_ptr()) };
CFString::from_raw(ptr).expect("CFLocale identifier should be non-null")
}
}
impl CFCalendar {
#[must_use]
pub fn current() -> Self {
let ptr = unsafe { ffi::cf_calendar_copy_current() };
Self::from_raw(ptr).expect("CFCalendarCopyCurrent returned NULL")
}
#[must_use]
pub fn new(identifier: &str) -> Self {
let identifier = to_cstring(identifier);
let ptr = unsafe { ffi::cf_calendar_create(identifier.as_ptr()) };
Self::from_raw(ptr).expect("CFCalendarCreateWithIdentifier returned NULL")
}
#[must_use]
pub fn identifier(&self) -> CFString {
let ptr = unsafe { ffi::cf_calendar_copy_identifier(self.as_ptr()) };
CFString::from_raw(ptr).expect("CFCalendar identifier should be non-null")
}
#[must_use]
pub fn time_zone(&self) -> CFTimeZone {
let ptr = unsafe { ffi::cf_calendar_copy_time_zone(self.as_ptr()) };
CFTimeZone::from_raw(ptr).expect("CFCalendarCopyTimeZone returned NULL")
}
pub fn set_time_zone(&self, time_zone: &CFTimeZone) {
unsafe { ffi::cf_calendar_set_time_zone(self.as_ptr(), time_zone.as_ptr()) };
}
}
impl CFTimeZone {
#[must_use]
pub fn current() -> Self {
let ptr = unsafe { ffi::cf_time_zone_copy_current() };
Self::from_raw(ptr).expect("CFTimeZoneCopyCurrent returned NULL")
}
#[must_use]
pub fn new(name: &str) -> Self {
let name = to_cstring(name);
let ptr = unsafe { ffi::cf_time_zone_create(name.as_ptr()) };
Self::from_raw(ptr).expect("CFTimeZoneCreateWithName returned NULL")
}
#[must_use]
pub fn name(&self) -> CFString {
let ptr = unsafe { ffi::cf_time_zone_copy_name(self.as_ptr()) };
CFString::from_raw(ptr).expect("CFTimeZoneGetName returned NULL")
}
#[must_use]
pub fn seconds_from_gmt(&self, date: &CFDate) -> i32 {
unsafe { ffi::cf_time_zone_get_seconds_from_gmt(self.as_ptr(), date.as_ptr()) }
}
}
impl CFCharacterSet {
#[must_use]
pub fn from_characters_in_string(string: &CFString) -> Self {
let ptr =
unsafe { ffi::cf_character_set_create_with_characters_in_string(string.as_ptr()) };
Self::from_raw(ptr).expect("CFCharacterSetCreateWithCharactersInString returned NULL")
}
#[must_use]
pub fn inverted(&self) -> Self {
let ptr = unsafe { ffi::cf_character_set_create_inverted_set(self.as_ptr()) };
Self::from_raw(ptr).expect("CFCharacterSetCreateInvertedSet returned NULL")
}
#[must_use]
pub fn contains(&self, character: char) -> bool {
unsafe { ffi::cf_character_set_is_character_member(self.as_ptr(), u32::from(character)) }
}
}
impl CFNumberFormatter {
#[must_use]
pub fn new(locale: Option<&CFLocale>, style: CFNumberFormatterStyle) -> Self {
let ptr = unsafe {
ffi::cf_number_formatter_create(
locale.map_or(std::ptr::null_mut(), CFLocale::as_ptr),
style as i32,
)
};
Self::from_raw(ptr).expect("CFNumberFormatterCreate returned NULL")
}
#[must_use]
pub fn format_number(&self, number: &CFNumber) -> CFString {
let ptr = unsafe {
ffi::cf_number_formatter_create_string_with_number(self.as_ptr(), number.as_ptr())
};
CFString::from_raw(ptr).expect("CFNumberFormatterCreateStringWithNumber returned NULL")
}
#[must_use]
pub fn parse_number(&self, string: &CFString) -> Option<CFNumber> {
let ptr = unsafe {
ffi::cf_number_formatter_create_number_from_string(self.as_ptr(), string.as_ptr())
};
CFNumber::from_raw(ptr)
}
}
impl CFDateFormatter {
#[must_use]
pub fn new(
locale: Option<&CFLocale>,
date_style: CFDateFormatterStyle,
time_style: CFDateFormatterStyle,
) -> Self {
let ptr = unsafe {
ffi::cf_date_formatter_create(
locale.map_or(std::ptr::null_mut(), CFLocale::as_ptr),
date_style as i32,
time_style as i32,
)
};
Self::from_raw(ptr).expect("CFDateFormatterCreate returned NULL")
}
#[must_use]
pub fn format_date(&self, date: &CFDate) -> CFString {
let ptr =
unsafe { ffi::cf_date_formatter_create_string_with_date(self.as_ptr(), date.as_ptr()) };
CFString::from_raw(ptr).expect("CFDateFormatterCreateStringWithDate returned NULL")
}
}
impl CFFileSecurity {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { ffi::cf_file_security_create() };
Self::from_raw(ptr).expect("CFFileSecurityCreate returned NULL")
}
#[must_use]
pub fn owner_uuid(&self) -> Option<CFUUID> {
let ptr = unsafe { ffi::cf_file_security_copy_owner_uuid(self.as_ptr()) };
CFUUID::from_raw(ptr)
}
#[must_use]
pub fn set_owner_uuid(&self, uuid: &CFUUID) -> bool {
unsafe { ffi::cf_file_security_set_owner_uuid(self.as_ptr(), uuid.as_ptr()) }
}
#[must_use]
pub fn mode(&self) -> Option<u32> {
let mut mode = 0_u32;
let ok = unsafe { ffi::cf_file_security_get_mode(self.as_ptr(), &mut mode) };
ok.then_some(mode)
}
#[must_use]
pub fn set_mode(&self, mode: u32) -> bool {
unsafe { ffi::cf_file_security_set_mode(self.as_ptr(), mode) }
}
}
impl Default for CFFileSecurity {
fn default() -> Self {
Self::new()
}
}
pub struct CFPreferences;
impl CFPreferences {
pub fn set_app_value(key: &CFString, value: Option<&dyn AsCFType>, app_id: &CFString) {
unsafe {
ffi::cf_preferences_set_app_value(
key.as_ptr(),
value.map_or(std::ptr::null_mut(), AsCFType::as_ptr),
app_id.as_ptr(),
);
}
}
#[must_use]
pub fn app_value(key: &CFString, app_id: &CFString) -> Option<CFType> {
let ptr = unsafe { ffi::cf_preferences_copy_app_value(key.as_ptr(), app_id.as_ptr()) };
CFType::from_raw(ptr)
}
#[must_use]
pub fn synchronize(app_id: &CFString) -> bool {
unsafe { ffi::cf_preferences_app_synchronize(app_id.as_ptr()) }
}
}
pub struct CFXML;
impl CFXML {
#[must_use]
pub fn escape_entities(value: &CFString) -> CFString {
let ptr = unsafe { ffi::cf_xml_create_string_by_escaping_entities(value.as_ptr()) };
CFString::from_raw(ptr).expect("CFXMLCreateStringByEscapingEntities returned NULL")
}
#[must_use]
pub fn unescape_entities(value: &CFString) -> CFString {
let ptr = unsafe { ffi::cf_xml_create_string_by_unescaping_entities(value.as_ptr()) };
CFString::from_raw(ptr).expect("CFXMLCreateStringByUnescapingEntities returned NULL")
}
}