1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use std::{
    io::ErrorKind,
    time::{Duration, SystemTime},
};

use chrono::prelude::*;

use crate::scanner_rust::{generic_array::typenum::U24, ScannerAscii, ScannerError};

#[derive(Default, Debug, Clone)]
pub struct Uptime {
    pub total_uptime:      Duration,
    pub all_cpu_idle_time: Duration,
}

impl Uptime {
    /// Get the btime (boot time) by subtract this uptime from the current unix epoch timestamp.
    ///
    /// ```rust
    /// use mprober_lib::uptime;
    ///
    /// let uptime = uptime::get_uptime().unwrap();
    /// let btime = uptime.get_btime();
    ///
    /// println!("{btime}");
    /// ```
    #[inline]
    pub fn get_btime(&self) -> DateTime<Utc> {
        (SystemTime::now() - self.total_uptime).into()
    }
}

/// Get the uptime by reading the `/proc/uptime` file.
///
/// ```rust
/// use mprober_lib::uptime;
///
/// let uptime = uptime::get_uptime().unwrap();
///
/// println!("{uptime:#?}");
/// ```
#[inline]
pub fn get_uptime() -> Result<Uptime, ScannerError> {
    let mut sc: ScannerAscii<_, U24> = ScannerAscii::scan_path2("/proc/uptime")?;

    let uptime = sc.next_f64()?.ok_or(ErrorKind::UnexpectedEof)?;
    let idle_time = sc.next_f64()?.ok_or(ErrorKind::UnexpectedEof)?;

    Ok(Uptime {
        total_uptime:      Duration::from_secs_f64(uptime),
        all_cpu_idle_time: Duration::from_secs_f64(idle_time),
    })
}