1use std::ffi::c_void;
29use std::ptr::NonNull;
30
31use mtl_sys::{class, msg_send_0, msg_send_1, msg_send_2, sel};
32
33use crate::array::Array;
34use crate::dictionary::Dictionary;
35use crate::object::{Object, Referencing};
36use crate::string::String;
37use crate::types::{Integer, OperatingSystemVersion, TimeInterval, UInteger};
38
39#[repr(transparent)]
43#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
44pub struct ProcessInfoThermalState(pub Integer);
45
46impl ProcessInfoThermalState {
47 pub const NOMINAL: Self = Self(0);
49 pub const FAIR: Self = Self(1);
51 pub const SERIOUS: Self = Self(2);
53 pub const CRITICAL: Self = Self(3);
55}
56
57#[repr(transparent)]
61#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
62pub struct ActivityOptions(pub u64);
63
64impl ActivityOptions {
65 pub const IDLE_DISPLAY_SLEEP_DISABLED: Self = Self(1 << 40);
67 pub const IDLE_SYSTEM_SLEEP_DISABLED: Self = Self(1 << 20);
69 pub const SUDDEN_TERMINATION_DISABLED: Self = Self(1 << 14);
71 pub const AUTOMATIC_TERMINATION_DISABLED: Self = Self(1 << 15);
73 pub const USER_INITIATED: Self = Self(0x00FFFFFF | (1 << 20));
75 pub const USER_INITIATED_ALLOWING_IDLE_SYSTEM_SLEEP: Self = Self(0x00FFFFFF);
77 pub const BACKGROUND: Self = Self(0x000000FF);
79 pub const LATENCY_CRITICAL: Self = Self(0xFF00000000);
81
82 #[inline]
84 pub const fn bits(&self) -> u64 {
85 self.0
86 }
87
88 #[inline]
90 pub const fn from_bits(bits: u64) -> Self {
91 Self(bits)
92 }
93}
94
95impl std::ops::BitOr for ActivityOptions {
96 type Output = Self;
97 #[inline]
98 fn bitor(self, rhs: Self) -> Self {
99 Self(self.0 | rhs.0)
100 }
101}
102
103impl std::ops::BitAnd for ActivityOptions {
104 type Output = Self;
105 #[inline]
106 fn bitand(self, rhs: Self) -> Self {
107 Self(self.0 & rhs.0)
108 }
109}
110
111pub type DeviceCertification = Integer;
115
116pub type ProcessPerformanceProfile = Integer;
120
121#[repr(transparent)]
125#[derive(Clone)]
126pub struct ProcessInfo(NonNull<c_void>);
127
128impl ProcessInfo {
129 #[inline]
133 pub fn process_info() -> Option<Self> {
134 unsafe {
135 let ptr: *mut c_void = msg_send_0(class!(NSProcessInfo).as_ptr(), sel!(processInfo));
136 Self::from_ptr(ptr)
137 }
138 }
139
140 #[inline]
144 pub fn arguments(&self) -> *mut Array<String> {
145 unsafe { msg_send_0(self.as_ptr(), sel!(arguments)) }
146 }
147
148 #[inline]
152 pub fn environment(&self) -> *mut Dictionary {
153 unsafe { msg_send_0(self.as_ptr(), sel!(environment)) }
154 }
155
156 #[inline]
160 pub fn host_name(&self) -> *mut String {
161 unsafe { msg_send_0(self.as_ptr(), sel!(hostName)) }
162 }
163
164 #[inline]
168 pub fn process_name(&self) -> *mut String {
169 unsafe { msg_send_0(self.as_ptr(), sel!(processName)) }
170 }
171
172 #[inline]
176 pub fn set_process_name(&self, name: &String) {
177 unsafe {
178 let _: () = msg_send_1(self.as_ptr(), sel!(setProcessName:), name.as_ptr());
179 }
180 }
181
182 #[inline]
186 pub fn process_identifier(&self) -> i32 {
187 unsafe { msg_send_0(self.as_ptr(), sel!(processIdentifier)) }
188 }
189
190 #[inline]
194 pub fn globally_unique_string(&self) -> *mut String {
195 unsafe { msg_send_0(self.as_ptr(), sel!(globallyUniqueString)) }
196 }
197
198 #[inline]
200 pub fn user_name(&self) -> *mut String {
201 unsafe { msg_send_0(self.as_ptr(), sel!(userName)) }
202 }
203
204 #[inline]
206 pub fn full_user_name(&self) -> *mut String {
207 unsafe { msg_send_0(self.as_ptr(), sel!(fullUserName)) }
208 }
209
210 #[inline]
214 pub fn operating_system(&self) -> UInteger {
215 unsafe { msg_send_0(self.as_ptr(), sel!(operatingSystem)) }
216 }
217
218 #[inline]
222 pub fn operating_system_version(&self) -> OperatingSystemVersion {
223 unsafe { msg_send_0(self.as_ptr(), sel!(operatingSystemVersion)) }
224 }
225
226 #[inline]
230 pub fn operating_system_version_string(&self) -> *mut String {
231 unsafe { msg_send_0(self.as_ptr(), sel!(operatingSystemVersionString)) }
232 }
233
234 #[inline]
238 pub fn is_operating_system_at_least_version(&self, version: OperatingSystemVersion) -> bool {
239 unsafe {
240 msg_send_1(
241 self.as_ptr(),
242 sel!(isOperatingSystemAtLeastVersion:),
243 version,
244 )
245 }
246 }
247
248 #[inline]
252 pub fn processor_count(&self) -> UInteger {
253 unsafe { msg_send_0(self.as_ptr(), sel!(processorCount)) }
254 }
255
256 #[inline]
260 pub fn active_processor_count(&self) -> UInteger {
261 unsafe { msg_send_0(self.as_ptr(), sel!(activeProcessorCount)) }
262 }
263
264 #[inline]
268 pub fn physical_memory(&self) -> u64 {
269 unsafe { msg_send_0(self.as_ptr(), sel!(physicalMemory)) }
270 }
271
272 #[inline]
276 pub fn system_uptime(&self) -> TimeInterval {
277 unsafe { msg_send_0(self.as_ptr(), sel!(systemUptime)) }
278 }
279
280 #[inline]
284 pub fn disable_sudden_termination(&self) {
285 unsafe {
286 msg_send_0::<()>(self.as_ptr(), sel!(disableSuddenTermination));
287 }
288 }
289
290 #[inline]
294 pub fn enable_sudden_termination(&self) {
295 unsafe {
296 msg_send_0::<()>(self.as_ptr(), sel!(enableSuddenTermination));
297 }
298 }
299
300 #[inline]
304 pub fn disable_automatic_termination(&self, reason: &String) {
305 unsafe {
306 let _: () = msg_send_1(
307 self.as_ptr(),
308 sel!(disableAutomaticTermination:),
309 reason.as_ptr(),
310 );
311 }
312 }
313
314 #[inline]
318 pub fn enable_automatic_termination(&self, reason: &String) {
319 unsafe {
320 let _: () = msg_send_1(
321 self.as_ptr(),
322 sel!(enableAutomaticTermination:),
323 reason.as_ptr(),
324 );
325 }
326 }
327
328 #[inline]
332 pub fn automatic_termination_support_enabled(&self) -> bool {
333 unsafe { msg_send_0(self.as_ptr(), sel!(automaticTerminationSupportEnabled)) }
334 }
335
336 #[inline]
340 pub fn set_automatic_termination_support_enabled(&self, enabled: bool) {
341 unsafe {
342 let _: () = msg_send_1(
343 self.as_ptr(),
344 sel!(setAutomaticTerminationSupportEnabled:),
345 enabled,
346 );
347 }
348 }
349
350 #[inline]
354 pub fn begin_activity(&self, options: ActivityOptions, reason: &String) -> *mut Object {
355 unsafe {
356 msg_send_2(
357 self.as_ptr(),
358 sel!(beginActivityWithOptions:reason:),
359 options.0,
360 reason.as_ptr(),
361 )
362 }
363 }
364
365 #[inline]
369 pub fn end_activity(&self, activity: &Object) {
370 unsafe {
371 let _: () = msg_send_1(self.as_ptr(), sel!(endActivity:), activity.as_ptr());
372 }
373 }
374
375 #[inline]
379 pub fn thermal_state(&self) -> ProcessInfoThermalState {
380 unsafe { msg_send_0(self.as_ptr(), sel!(thermalState)) }
381 }
382
383 #[inline]
387 pub fn is_low_power_mode_enabled(&self) -> bool {
388 unsafe { msg_send_0(self.as_ptr(), sel!(isLowPowerModeEnabled)) }
389 }
390
391 #[inline]
395 pub fn is_ios_app_on_mac(&self) -> bool {
396 unsafe { msg_send_0(self.as_ptr(), sel!(isiOSAppOnMac)) }
397 }
398
399 #[inline]
403 pub fn is_mac_catalyst_app(&self) -> bool {
404 unsafe { msg_send_0(self.as_ptr(), sel!(isMacCatalystApp)) }
405 }
406
407 #[inline]
411 pub fn is_device_certified(&self, performance_tier: DeviceCertification) -> bool {
412 unsafe { msg_send_1(self.as_ptr(), sel!(isDeviceCertified:), performance_tier) }
413 }
414
415 #[inline]
419 pub fn has_performance_profile(&self, performance_profile: ProcessPerformanceProfile) -> bool {
420 unsafe {
421 msg_send_1(
422 self.as_ptr(),
423 sel!(hasPerformanceProfile:),
424 performance_profile,
425 )
426 }
427 }
428
429 #[inline]
435 pub unsafe fn from_ptr(ptr: *mut c_void) -> Option<Self> {
436 NonNull::new(ptr).map(Self)
437 }
438}
439
440impl Referencing for ProcessInfo {
441 #[inline]
442 fn as_ptr(&self) -> *const c_void {
443 self.0.as_ptr()
444 }
445}
446
447unsafe impl Send for ProcessInfo {}
448unsafe impl Sync for ProcessInfo {}
449
450impl std::fmt::Debug for ProcessInfo {
451 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
452 f.debug_struct("ProcessInfo").field("ptr", &self.0).finish()
453 }
454}
455
456#[cfg(test)]
457mod tests {
458 use super::*;
459
460 #[test]
461 fn test_process_info_size() {
462 assert_eq!(
463 std::mem::size_of::<ProcessInfo>(),
464 std::mem::size_of::<*mut c_void>()
465 );
466 }
467
468 #[test]
469 fn test_thermal_state_values() {
470 assert_eq!(ProcessInfoThermalState::NOMINAL.0, 0);
471 assert_eq!(ProcessInfoThermalState::FAIR.0, 1);
472 assert_eq!(ProcessInfoThermalState::SERIOUS.0, 2);
473 assert_eq!(ProcessInfoThermalState::CRITICAL.0, 3);
474 }
475}