From 94e43d7fa1f09dd1df030af97f3cf927a2f231b8 Mon Sep 17 00:00:00 2001 From: Yury Date: Fri, 28 Feb 2025 12:32:34 +0300 Subject: [PATCH] ns::UserDefaults --- cidre/pomace/ns/ns.h | 3 + cidre/src/ns.rs | 3 + cidre/src/ns/user_defaults.rs | 159 ++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 cidre/src/ns/user_defaults.rs diff --git a/cidre/pomace/ns/ns.h b/cidre/pomace/ns/ns.h index 84d6277a..76d203a7 100644 --- a/cidre/pomace/ns/ns.h +++ b/cidre/pomace/ns/ns.h @@ -83,6 +83,8 @@ Class NS_XPC_INTERFACE; Class NS_THREAD; Class NS_BUNDLE; +Class NS_USER_DEFAULTS; + typedef void cidre_change( void * _Nullable, NSString * _Nullable, @@ -179,6 +181,7 @@ static void common_initializer(void) NS_THREAD = [NSThread class]; NS_BUNDLE = [NSBundle class]; + NS_USER_DEFAULTS = [NSUserDefaults class]; } } NS_ASSUME_NONNULL_END diff --git a/cidre/src/ns.rs b/cidre/src/ns.rs index 893a1be6..06da3a0a 100644 --- a/cidre/src/ns.rs +++ b/cidre/src/ns.rs @@ -85,6 +85,9 @@ pub use url_cache::CachedUrlResponse; pub use url_cache::StoragePolicy as UrlCacheStoragePolicy; pub use url_cache::UrlCache; +mod user_defaults; +pub use user_defaults::UserDefaults; + mod value; pub use value::Number; pub use value::Value; diff --git a/cidre/src/ns/user_defaults.rs b/cidre/src/ns/user_defaults.rs new file mode 100644 index 00000000..e668a078 --- /dev/null +++ b/cidre/src/ns/user_defaults.rs @@ -0,0 +1,159 @@ +use crate::{ + arc, define_obj_type, ns, + objc::{self, Obj}, +}; + +define_obj_type!( + #[doc(alias = "NSUserDefaults")] + pub UserDefaults(ns::Id), + NS_USER_DEFAULTS +); + +impl arc::A { + #[objc::msg_send(initWithSuiteName:)] + pub fn init_with_suite_name(self, name: Option<&ns::String>) -> Option>; +} + +impl UserDefaults { + #[objc::msg_send(standardUserDefaults)] + pub fn standard() -> arc::R; + + #[objc::msg_send(resetStandardUserDefaults)] + pub fn reset(); + + pub fn with_suite_name(name: Option<&ns::String>) -> Option> { + Self::alloc().init_with_suite_name(name) + } + + #[objc::msg_send(objectForKey:)] + pub fn get_obj(&self, key: &ns::String) -> Option>; + + #[objc::msg_send(setObject:forKey:)] + pub fn set_obj_for_key(&mut self, val: Option<&ns::Id>, key: &ns::String); + + #[inline] + pub fn set_obj(&mut self, key: &ns::String, val: Option<&ns::Id>) { + self.set_obj_for_key(val, key) + } + + #[objc::msg_send(stringForKey:)] + pub fn get_string(&self, key: &ns::String) -> Option>; + + #[objc::msg_send(arrayForKey:)] + pub fn get_array(&self, key: &ns::String) -> Option>>; + + #[objc::msg_send(dictionaryForKey:)] + pub fn get_dictionary( + &self, + key: &ns::String, + ) -> Option>>; + + #[objc::msg_send(dataForKey:)] + pub fn get_data(&self, key: &ns::String) -> Option>; + + #[objc::msg_send(stringArrayForKey:)] + pub fn get_string_array(&self, key: &ns::String) -> Option>>; + + #[objc::msg_send(integerForKey:)] + pub fn get_integer(&self, key: &ns::String) -> ns::Integer; + + #[objc::msg_send(floatForKey:)] + pub fn get_f32(&self, key: &ns::String) -> f32; + + #[objc::msg_send(doubleForKey:)] + pub fn get_f64(&self, key: &ns::String) -> f64; + + #[objc::msg_send(boolForKey:)] + pub fn get_bool(&self, key: &ns::String) -> bool; + + #[objc::msg_send(URLForKey:)] + pub fn get_url(&self, key: &ns::String) -> Option>; + + #[objc::msg_send(setInteger:forKey:)] + pub fn set_integer_for_key(&mut self, val: ns::Integer, key: &ns::String); + + #[inline] + pub fn set_integer(&mut self, key: &ns::String, val: ns::Integer) { + self.set_integer_for_key(val, key); + } + + #[objc::msg_send(setFloat:forKey:)] + pub fn set_f32_for_key(&mut self, val: f32, key: &ns::String); + + #[inline] + pub fn set_f32(&mut self, key: &ns::String, val: f32) { + self.set_f32_for_key(val, key); + } + + #[objc::msg_send(setDouble:forKey:)] + pub fn set_f64_for_key(&mut self, val: f64, key: &ns::String); + + #[inline] + pub fn set_f64(&mut self, key: &ns::String, val: f64) { + self.set_f64_for_key(val, key); + } + + #[objc::msg_send(setURL:forKey:)] + pub fn set_url_for_key(&mut self, val: &ns::Url, key: &ns::String); + + #[inline] + pub fn set_url(&mut self, key: &ns::String, val: &ns::Url) { + self.set_url_for_key(val, key); + } + + pub fn set_u64(&mut self, key: &ns::String, val: u64) { + let val = ns::Number::with_u64(val); + self.set_obj(key, Some(&val)); + } + + pub fn get_u64(&self, key: &ns::String) -> u64 { + let Some(obj) = self.get_obj(key) else { + return 0; + }; + + let Some(num) = obj.try_cast(ns::Number::cls()) else { + return 0; + }; + + num.as_u64() + } +} + +impl ns::KvObserverRegistration for UserDefaults {} + +unsafe impl Send for UserDefaults {} +unsafe impl Sync for UserDefaults {} + +#[link(name = "ns", kind = "static")] +unsafe extern "C" { + static NS_USER_DEFAULTS: &'static objc::Class; +} + +#[cfg(test)] +mod tests { + use crate::ns; + + #[test] + fn basics() { + let mut ud = ns::UserDefaults::standard(); + let key = ns::str!(c"unknown"); + + assert!(ud.get_obj(key).is_none()); + assert!(ud.get_string(key).is_none()); + assert!(ud.get_array(key).is_none()); + assert!(ud.get_data(key).is_none()); + assert!(ud.get_string_array(key).is_none()); + assert!(ud.get_url(key).is_none()); + + assert_eq!(ud.get_bool(key), false); + assert_eq!(ud.get_f32(key), 0.0); + assert_eq!(ud.get_f64(key), 0.0); + assert_eq!(ud.get_integer(key), 0); + + let key = ns::str!(c"u64"); + ud.set_u64(key, u64::MAX); + assert_eq!(ud.get_u64(key), u64::MAX); + ud.set_u64(key, u64::MIN); + assert_eq!(ud.get_u64(key), u64::MIN); + } +}