Skip to main content

mtl_foundation/
date.rs

1//! Date type for Foundation.
2//!
3//! Corresponds to `Foundation/NSDate.hpp`.
4//!
5//! # C++ Equivalent
6//!
7//! ```cpp
8//! namespace NS {
9//! using TimeInterval = double;
10//!
11//! class Date : public Copying<Date> {
12//! public:
13//!     static Date* dateWithTimeIntervalSinceNow(TimeInterval secs);
14//! };
15//! }
16//! ```
17
18use std::ffi::c_void;
19use std::ptr::NonNull;
20
21use mtl_sys::{class, msg_send_0, msg_send_1, sel};
22
23use crate::object::{Copying, Referencing};
24use crate::types::TimeInterval;
25
26/// An Objective-C date object.
27///
28/// C++ equivalent: `NS::Date`
29#[repr(transparent)]
30#[derive(Clone)]
31pub struct Date(NonNull<c_void>);
32
33impl Date {
34    /// Create a date with a time interval since now.
35    ///
36    /// C++ equivalent: `static Date* dateWithTimeIntervalSinceNow(TimeInterval secs)`
37    #[inline]
38    pub fn date_with_time_interval_since_now(secs: TimeInterval) -> Option<Self> {
39        unsafe {
40            let ptr: *mut c_void = msg_send_1(
41                class!(NSDate).as_ptr(),
42                sel!(dateWithTimeIntervalSinceNow:),
43                secs,
44            );
45            Self::from_ptr(ptr)
46        }
47    }
48
49    /// Create a Date from a raw pointer.
50    ///
51    /// # Safety
52    ///
53    /// The pointer must be a valid Objective-C NSDate object.
54    #[inline]
55    pub unsafe fn from_ptr(ptr: *mut c_void) -> Option<Self> {
56        NonNull::new(ptr).map(Self)
57    }
58}
59
60impl Referencing for Date {
61    #[inline]
62    fn as_ptr(&self) -> *const c_void {
63        self.0.as_ptr()
64    }
65}
66
67impl Copying for Date {
68    #[inline]
69    fn copy(&self) -> Option<Self> {
70        unsafe {
71            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
72            Self::from_ptr(ptr)
73        }
74    }
75}
76
77unsafe impl Send for Date {}
78unsafe impl Sync for Date {}
79
80impl std::fmt::Debug for Date {
81    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82        f.debug_struct("Date").field("ptr", &self.0).finish()
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_date_size() {
92        assert_eq!(
93            std::mem::size_of::<Date>(),
94            std::mem::size_of::<*mut c_void>()
95        );
96    }
97}