notify_rust/
timeout.rs

1use std::{num::ParseIntError, str::FromStr, time::Duration};
2
3/// Describes the timeout of a notification
4///
5/// # `FromStr`
6/// You can also parse a `Timeout` from a `&str`.
7/// ```
8/// # use notify_rust::Timeout;
9/// assert_eq!("default".parse(), Ok(Timeout::Default));
10/// assert_eq!("never".parse(), Ok(Timeout::Never));
11/// assert_eq!("42".parse(), Ok(Timeout::Milliseconds(42)));
12/// ```
13#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
14pub enum Timeout {
15    /// Expires according to server default.
16    ///
17    /// Whatever that might be...
18    #[default]
19    Default,
20
21    /// Do not expire, user will have to close this manually.
22    Never,
23
24    /// Expire after n milliseconds.
25    Milliseconds(u32),
26}
27
28#[test]
29fn timeout_from_i32() {
30    assert_eq!(Timeout::from(234), Timeout::Milliseconds(234));
31    assert_eq!(Timeout::from(-234), Timeout::Default);
32    assert_eq!(Timeout::from(0), Timeout::Never);
33}
34
35impl From<i32> for Timeout {
36    fn from(int: i32) -> Timeout {
37        use std::cmp::Ordering::*;
38        match int.cmp(&0) {
39            Greater => Timeout::Milliseconds(int as u32),
40            Less => Timeout::Default,
41            Equal => Timeout::Never,
42        }
43    }
44}
45
46impl From<Duration> for Timeout {
47    fn from(duration: Duration) -> Timeout {
48        if duration.is_zero() {
49            Timeout::Never
50        } else if duration.as_millis() > u32::MAX as u128 {
51            Timeout::Default
52        } else {
53            Timeout::Milliseconds(duration.as_millis().try_into().unwrap_or(u32::MAX))
54        }
55    }
56}
57
58impl From<Timeout> for i32 {
59    fn from(timeout: Timeout) -> Self {
60        match timeout {
61            Timeout::Default => -1,
62            Timeout::Never => 0,
63            Timeout::Milliseconds(ms) => ms as i32,
64        }
65    }
66}
67
68impl FromStr for Timeout {
69    type Err = ParseIntError;
70
71    fn from_str(s: &str) -> Result<Self, Self::Err> {
72        match s {
73            "default" => Ok(Timeout::Default),
74            "never" => Ok(Timeout::Never),
75            milliseconds => Ok(Timeout::Milliseconds(u32::from_str(milliseconds)?)),
76        }
77    }
78}
79
80pub struct TimeoutMessage(Timeout);
81
82impl From<Timeout> for TimeoutMessage {
83    fn from(hint: Timeout) -> Self {
84        TimeoutMessage(hint)
85    }
86}
87
88impl std::ops::Deref for TimeoutMessage {
89    type Target = Timeout;
90
91    fn deref(&self) -> &Self::Target {
92        &self.0
93    }
94}
95
96#[cfg(all(feature = "dbus", unix, not(target_os = "macos")))]
97impl TryFrom<&dbus::arg::messageitem::MessageItem> for TimeoutMessage {
98    type Error = ();
99
100    fn try_from(mi: &dbus::arg::messageitem::MessageItem) -> Result<TimeoutMessage, ()> {
101        mi.inner::<i32>().map(|i| TimeoutMessage(i.into()))
102    }
103}