1use std::ffi::c_void;
33use std::ptr::NonNull;
34
35use mtl_sys::{class, msg_send_0, msg_send_1, msg_send_3, sel};
36
37use crate::array::Array;
38use crate::dictionary::Dictionary;
39use crate::error::Error;
40use crate::object::{Object, Referencing};
41use crate::string::String;
42use crate::url::Url;
43
44#[repr(transparent)]
48#[derive(Clone)]
49pub struct Bundle(NonNull<c_void>);
50
51impl Bundle {
52 #[inline]
56 pub fn main_bundle() -> Option<Self> {
57 unsafe {
58 let ptr: *mut c_void = msg_send_0(class!(NSBundle).as_ptr(), sel!(mainBundle));
59 Self::from_ptr(ptr)
60 }
61 }
62
63 #[inline]
67 pub fn bundle_with_path(path: &String) -> Option<Self> {
68 unsafe {
69 let ptr: *mut c_void = msg_send_1(
70 class!(NSBundle).as_ptr(),
71 sel!(bundleWithPath:),
72 path.as_ptr(),
73 );
74 Self::from_ptr(ptr)
75 }
76 }
77
78 #[inline]
82 pub fn bundle_with_url(url: &Url) -> Option<Self> {
83 unsafe {
84 let ptr: *mut c_void = msg_send_1(
85 class!(NSBundle).as_ptr(),
86 sel!(bundleWithURL:),
87 url.as_ptr(),
88 );
89 Self::from_ptr(ptr)
90 }
91 }
92
93 #[inline]
97 pub fn all_bundles() -> *mut Array<Bundle> {
98 unsafe { msg_send_0(class!(NSBundle).as_ptr(), sel!(allBundles)) }
99 }
100
101 #[inline]
105 pub fn all_frameworks() -> *mut Array<Bundle> {
106 unsafe { msg_send_0(class!(NSBundle).as_ptr(), sel!(allFrameworks)) }
107 }
108
109 #[inline]
113 pub fn alloc() -> Option<Self> {
114 unsafe {
115 let ptr: *mut c_void = msg_send_0(class!(NSBundle).as_ptr(), sel!(alloc));
116 Self::from_ptr(ptr)
117 }
118 }
119
120 #[inline]
124 pub fn init_with_path(&self, path: &String) -> Option<Self> {
125 unsafe {
126 let ptr: *mut c_void = msg_send_1(self.as_ptr(), sel!(initWithPath:), path.as_ptr());
127 Self::from_ptr(ptr)
128 }
129 }
130
131 #[inline]
135 pub fn init_with_url(&self, url: &Url) -> Option<Self> {
136 unsafe {
137 let ptr: *mut c_void = msg_send_1(self.as_ptr(), sel!(initWithURL:), url.as_ptr());
138 Self::from_ptr(ptr)
139 }
140 }
141
142 #[inline]
146 pub fn load(&self) -> bool {
147 unsafe { msg_send_0(self.as_ptr(), sel!(load)) }
148 }
149
150 #[inline]
154 pub fn unload(&self) -> bool {
155 unsafe { msg_send_0(self.as_ptr(), sel!(unload)) }
156 }
157
158 #[inline]
162 pub fn is_loaded(&self) -> bool {
163 unsafe { msg_send_0(self.as_ptr(), sel!(isLoaded)) }
164 }
165
166 #[inline]
170 pub fn preflight_and_return_error(&self, error: *mut *mut Error) -> bool {
171 unsafe { msg_send_1(self.as_ptr(), sel!(preflightAndReturnError:), error) }
172 }
173
174 #[inline]
178 pub fn load_and_return_error(&self, error: *mut *mut Error) -> bool {
179 unsafe { msg_send_1(self.as_ptr(), sel!(loadAndReturnError:), error) }
180 }
181
182 #[inline]
186 pub fn bundle_url(&self) -> *mut Url {
187 unsafe { msg_send_0(self.as_ptr(), sel!(bundleURL)) }
188 }
189
190 #[inline]
194 pub fn resource_url(&self) -> *mut Url {
195 unsafe { msg_send_0(self.as_ptr(), sel!(resourceURL)) }
196 }
197
198 #[inline]
202 pub fn executable_url(&self) -> *mut Url {
203 unsafe { msg_send_0(self.as_ptr(), sel!(executableURL)) }
204 }
205
206 #[inline]
210 pub fn url_for_auxiliary_executable(&self, name: &String) -> *mut Url {
211 unsafe {
212 msg_send_1(
213 self.as_ptr(),
214 sel!(URLForAuxiliaryExecutable:),
215 name.as_ptr(),
216 )
217 }
218 }
219
220 #[inline]
222 pub fn private_frameworks_url(&self) -> *mut Url {
223 unsafe { msg_send_0(self.as_ptr(), sel!(privateFrameworksURL)) }
224 }
225
226 #[inline]
228 pub fn shared_frameworks_url(&self) -> *mut Url {
229 unsafe { msg_send_0(self.as_ptr(), sel!(sharedFrameworksURL)) }
230 }
231
232 #[inline]
234 pub fn shared_support_url(&self) -> *mut Url {
235 unsafe { msg_send_0(self.as_ptr(), sel!(sharedSupportURL)) }
236 }
237
238 #[inline]
240 pub fn built_in_plug_ins_url(&self) -> *mut Url {
241 unsafe { msg_send_0(self.as_ptr(), sel!(builtInPlugInsURL)) }
242 }
243
244 #[inline]
246 pub fn app_store_receipt_url(&self) -> *mut Url {
247 unsafe { msg_send_0(self.as_ptr(), sel!(appStoreReceiptURL)) }
248 }
249
250 #[inline]
254 pub fn bundle_path(&self) -> *mut String {
255 unsafe { msg_send_0(self.as_ptr(), sel!(bundlePath)) }
256 }
257
258 #[inline]
260 pub fn resource_path(&self) -> *mut String {
261 unsafe { msg_send_0(self.as_ptr(), sel!(resourcePath)) }
262 }
263
264 #[inline]
266 pub fn executable_path(&self) -> *mut String {
267 unsafe { msg_send_0(self.as_ptr(), sel!(executablePath)) }
268 }
269
270 #[inline]
272 pub fn path_for_auxiliary_executable(&self, name: &String) -> *mut String {
273 unsafe {
274 msg_send_1(
275 self.as_ptr(),
276 sel!(pathForAuxiliaryExecutable:),
277 name.as_ptr(),
278 )
279 }
280 }
281
282 #[inline]
284 pub fn private_frameworks_path(&self) -> *mut String {
285 unsafe { msg_send_0(self.as_ptr(), sel!(privateFrameworksPath)) }
286 }
287
288 #[inline]
290 pub fn shared_frameworks_path(&self) -> *mut String {
291 unsafe { msg_send_0(self.as_ptr(), sel!(sharedFrameworksPath)) }
292 }
293
294 #[inline]
296 pub fn shared_support_path(&self) -> *mut String {
297 unsafe { msg_send_0(self.as_ptr(), sel!(sharedSupportPath)) }
298 }
299
300 #[inline]
302 pub fn built_in_plug_ins_path(&self) -> *mut String {
303 unsafe { msg_send_0(self.as_ptr(), sel!(builtInPlugInsPath)) }
304 }
305
306 #[inline]
310 pub fn bundle_identifier(&self) -> *mut String {
311 unsafe { msg_send_0(self.as_ptr(), sel!(bundleIdentifier)) }
312 }
313
314 #[inline]
318 pub fn info_dictionary(&self) -> *mut Dictionary {
319 unsafe { msg_send_0(self.as_ptr(), sel!(infoDictionary)) }
320 }
321
322 #[inline]
326 pub fn localized_info_dictionary(&self) -> *mut Dictionary {
327 unsafe { msg_send_0(self.as_ptr(), sel!(localizedInfoDictionary)) }
328 }
329
330 #[inline]
334 pub fn object_for_info_dictionary_key(&self, key: &String) -> *mut Object {
335 unsafe {
336 msg_send_1(
337 self.as_ptr(),
338 sel!(objectForInfoDictionaryKey:),
339 key.as_ptr(),
340 )
341 }
342 }
343
344 #[inline]
348 pub fn localized_string(
349 &self,
350 key: &String,
351 value: *const String,
352 table_name: *const String,
353 ) -> *mut String {
354 unsafe {
355 msg_send_3(
356 self.as_ptr(),
357 sel!(localizedStringForKey:value:table:),
358 key.as_ptr(),
359 value,
360 table_name,
361 )
362 }
363 }
364
365 #[inline]
371 pub unsafe fn from_ptr(ptr: *mut c_void) -> Option<Self> {
372 NonNull::new(ptr).map(Self)
373 }
374}
375
376impl Referencing for Bundle {
377 #[inline]
378 fn as_ptr(&self) -> *const c_void {
379 self.0.as_ptr()
380 }
381}
382
383unsafe impl Send for Bundle {}
384unsafe impl Sync for Bundle {}
385
386impl std::fmt::Debug for Bundle {
387 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388 f.debug_struct("Bundle").field("ptr", &self.0).finish()
389 }
390}
391
392#[inline]
398pub fn localized_string(key: &String) -> *mut String {
399 if let Some(bundle) = Bundle::main_bundle() {
400 bundle.localized_string(key, std::ptr::null(), std::ptr::null())
401 } else {
402 std::ptr::null_mut()
403 }
404}
405
406#[inline]
410pub fn localized_string_from_table(key: &String, table: &String) -> *mut String {
411 if let Some(bundle) = Bundle::main_bundle() {
412 bundle.localized_string(key, std::ptr::null(), table)
413 } else {
414 std::ptr::null_mut()
415 }
416}
417
418#[inline]
422pub fn localized_string_from_table_in_bundle(
423 key: &String,
424 table: &String,
425 bundle: &Bundle,
426) -> *mut String {
427 bundle.localized_string(key, std::ptr::null(), table)
428}
429
430#[inline]
434pub fn localized_string_with_default_value(
435 key: &String,
436 table: &String,
437 bundle: &Bundle,
438 value: &String,
439) -> *mut String {
440 bundle.localized_string(key, value, table)
441}
442
443#[cfg(test)]
444mod tests {
445 use super::*;
446
447 #[test]
448 fn test_bundle_size() {
449 assert_eq!(
450 std::mem::size_of::<Bundle>(),
451 std::mem::size_of::<*mut c_void>()
452 );
453 }
454}