Skip to main content

ferroui_base/platform/
i_runtime_platform.rs

1/// Describes the platform the application runs on.
2pub trait IRuntimePlatform: 'static {
3    /// Information about the platform the application runs on.
4    fn get_runtime_info(&self) -> RuntimePlatformInfo;
5
6    // CLOCK-SEAM: the wall clock of the platform. The dispatcher clock
7    // (`IDispatcherImpl::now`) is monotonic and has no relation to calendar
8    // time, so "now" as a date is asked of the platform here. A platform
9    // without `std::time::SystemTime` — the browser (`wasm32-unknown-unknown`) —
10    // MUST register a runtime platform that overrides this (`Date.now()`);
11    // otherwise every "now" is the Unix epoch.
12    /// The current date and time in UTC, read by
13    /// [`DateTime::utc_now`](crate::utilities::DateTime::utc_now). The
14    /// default is for a platform without a wall clock: it reports the Unix
15    /// epoch, 1970-01-01T00:00:00 UTC.
16    fn get_utc_now(&self) -> crate::utilities::DateTime {
17        crate::utilities::DateTime::UNIX_EPOCH
18    }
19}
20
21/// Handles compare by identity (reference equality), so that they can be
22/// held in property and untyped values.
23impl PartialEq for dyn IRuntimePlatform {
24    #[inline]
25    fn eq(&self, other: &Self) -> bool {
26        std::ptr::addr_eq(self as *const Self, other as *const Self)
27    }
28}
29
30/// Information about the platform the application runs on.
31#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
32pub struct RuntimePlatformInfo {
33    /// Whether the platform is a desktop platform.
34    pub is_desktop: bool,
35    /// Whether the platform is a mobile platform.
36    pub is_mobile: bool,
37    /// Whether the platform is a TV platform.
38    pub is_tv: bool,
39}
40
41impl RuntimePlatformInfo {
42    /// The form factor of the platform.
43    pub fn form_factor(&self) -> FormFactorType {
44        if self.is_desktop {
45            FormFactorType::Desktop
46        } else if self.is_mobile {
47            FormFactorType::Mobile
48        } else if self.is_tv {
49            FormFactorType::TV
50        } else {
51            FormFactorType::Unknown
52        }
53    }
54}
55
56/// The form factor of a device.
57#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
58#[repr(i32)]
59pub enum FormFactorType {
60    #[default]
61    Unknown = 0,
62    Desktop = 1,
63    Mobile = 2,
64    TV = 3,
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn form_factor_prefers_desktop_then_mobile_then_tv() {
73        assert_eq!(RuntimePlatformInfo::default().form_factor(), FormFactorType::Unknown);
74        let all = RuntimePlatformInfo { is_desktop: true, is_mobile: true, is_tv: true };
75        assert_eq!(all.form_factor(), FormFactorType::Desktop);
76        let mobile_tv = RuntimePlatformInfo { is_desktop: false, is_mobile: true, is_tv: true };
77        assert_eq!(mobile_tv.form_factor(), FormFactorType::Mobile);
78        let tv = RuntimePlatformInfo { is_desktop: false, is_mobile: false, is_tv: true };
79        assert_eq!(tv.form_factor(), FormFactorType::TV);
80    }
81}