core_foundation/
bundle.rs1use core_foundation_sys::base::kCFAllocatorDefault;
13pub use core_foundation_sys::bundle::*;
14use core_foundation_sys::url::kCFURLPOSIXPathStyle;
15use std::path::PathBuf;
16
17use crate::base::{CFType, TCFType};
18use crate::dictionary::CFDictionary;
19use crate::string::CFString;
20use crate::url::CFURL;
21use std::os::raw::c_void;
22
23declare_TCFType! {
24 CFBundle, CFBundleRef
26}
27impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID);
28
29impl CFBundle {
30 pub fn new(bundleURL: CFURL) -> Option<CFBundle> {
31 unsafe {
32 let bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundleURL.as_concrete_TypeRef());
33 if bundle_ref.is_null() {
34 None
35 } else {
36 Some(TCFType::wrap_under_create_rule(bundle_ref))
37 }
38 }
39 }
40
41 pub fn bundle_with_identifier(identifier: CFString) -> Option<CFBundle> {
42 unsafe {
43 let bundle_ref = CFBundleGetBundleWithIdentifier(identifier.as_concrete_TypeRef());
44 if bundle_ref.is_null() {
45 None
46 } else {
47 Some(TCFType::wrap_under_get_rule(bundle_ref))
48 }
49 }
50 }
51
52 pub fn function_pointer_for_name(&self, function_name: CFString) -> *const c_void {
53 unsafe {
54 CFBundleGetFunctionPointerForName(
55 self.as_concrete_TypeRef(),
56 function_name.as_concrete_TypeRef(),
57 )
58 }
59 }
60
61 pub fn main_bundle() -> CFBundle {
62 unsafe {
63 let bundle_ref = CFBundleGetMainBundle();
64 TCFType::wrap_under_get_rule(bundle_ref)
65 }
66 }
67
68 pub fn info_dictionary(&self) -> CFDictionary<CFString, CFType> {
69 unsafe {
70 let info_dictionary = CFBundleGetInfoDictionary(self.0);
71 TCFType::wrap_under_get_rule(info_dictionary)
72 }
73 }
74
75 pub fn executable_url(&self) -> Option<CFURL> {
76 unsafe {
77 let exe_url = CFBundleCopyExecutableURL(self.0);
78 if exe_url.is_null() {
79 None
80 } else {
81 Some(TCFType::wrap_under_create_rule(exe_url))
82 }
83 }
84 }
85
86 pub fn bundle_url(&self) -> Option<CFURL> {
88 unsafe {
89 let bundle_url = CFBundleCopyBundleURL(self.0);
90 if bundle_url.is_null() {
91 None
92 } else {
93 Some(TCFType::wrap_under_create_rule(bundle_url))
94 }
95 }
96 }
97
98 pub fn path(&self) -> Option<PathBuf> {
100 let url = self.bundle_url()?;
101 Some(PathBuf::from(
102 url.get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
103 ))
104 }
105
106 pub fn bundle_resources_url(&self) -> Option<CFURL> {
108 unsafe {
109 let bundle_url = CFBundleCopyResourcesDirectoryURL(self.0);
110 if bundle_url.is_null() {
111 None
112 } else {
113 Some(TCFType::wrap_under_create_rule(bundle_url))
114 }
115 }
116 }
117
118 pub fn resources_path(&self) -> Option<PathBuf> {
120 let url = self.bundle_resources_url()?;
121 Some(PathBuf::from(
122 url.get_file_system_path(kCFURLPOSIXPathStyle).to_string(),
123 ))
124 }
125
126 pub fn private_frameworks_url(&self) -> Option<CFURL> {
127 unsafe {
128 let fw_url = CFBundleCopyPrivateFrameworksURL(self.0);
129 if fw_url.is_null() {
130 None
131 } else {
132 Some(TCFType::wrap_under_create_rule(fw_url))
133 }
134 }
135 }
136
137 pub fn shared_support_url(&self) -> Option<CFURL> {
138 unsafe {
139 let fw_url = CFBundleCopySharedSupportURL(self.0);
140 if fw_url.is_null() {
141 None
142 } else {
143 Some(TCFType::wrap_under_create_rule(fw_url))
144 }
145 }
146 }
147}
148
149#[test]
150fn safari_executable_url() {
151 use crate::string::CFString;
152 use crate::url::{kCFURLPOSIXPathStyle, CFURL};
153
154 let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
155 let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
156 let cfurl_executable = CFBundle::new(cfurl_path)
157 .expect("Safari not present")
158 .executable_url();
159 assert!(cfurl_executable.is_some());
160 assert_eq!(
161 cfurl_executable
162 .unwrap()
163 .absolute()
164 .get_file_system_path(kCFURLPOSIXPathStyle)
165 .to_string(),
166 "/Applications/Safari.app/Contents/MacOS/Safari"
167 );
168}
169
170#[test]
171fn safari_private_frameworks_url() {
172 use crate::string::CFString;
173 use crate::url::{kCFURLPOSIXPathStyle, CFURL};
174
175 let cfstr_path = CFString::from_static_string("/Applications/Safari.app");
176 let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
177 let cfurl_executable = CFBundle::new(cfurl_path)
178 .expect("Safari not present")
179 .private_frameworks_url();
180 assert!(cfurl_executable.is_some());
181 assert_eq!(
182 cfurl_executable
183 .unwrap()
184 .absolute()
185 .get_file_system_path(kCFURLPOSIXPathStyle)
186 .to_string(),
187 "/Applications/Safari.app/Contents/Frameworks"
188 );
189}
190
191#[test]
192fn non_existent_bundle() {
193 use crate::string::CFString;
194 use crate::url::{kCFURLPOSIXPathStyle, CFURL};
195
196 let cfstr_path = CFString::from_static_string("/usr/local/foo");
197 let cfurl_path = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
198 assert!(CFBundle::new(cfurl_path).is_none());
199}