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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use std::error::Error;
use std::fs::read_dir;
use std::path;

use crate::utils::*;

/// An enumeration of the states that the AC adapter system can be in.
#[derive(Clone, Debug, PartialEq)]
pub enum Status {
    /// AC adapter is connected and charging.
    Online,
    /// AC adapter is not connected or charging.
    Offline,
}

/// Information about AC adapters plugged into the system.
pub struct ACAdapterInfo {
    /// The name used by ACPI to refer to the adapter.
    pub name: String,
    /// Whether the adapter is plugged in and charging or not.
    pub status: Status,
}

/// Check the ACPI system for all AC adapters the OS knows about.
///
/// # Arguments
///
/// * `path` - The path to AC adapter entries produced by the ACPI subsystem.
pub fn get_ac_adapter_info(path: &path::Path) -> Result<Vec<ACAdapterInfo>, Box<dyn Error>> {
    let mut results: Vec<ACAdapterInfo> = vec![];

    for entry in read_dir(&path)? {
        let path = entry?.path();
        if !determine_is_battery(parse_entry_file(&path.join("type"))?) {
            let adapter = ACAdapterInfo::new(&path);
            if adapter.is_ok() {
                results.push(adapter?);
            }
        }
    }

    Ok(results)
}

impl ACAdapterInfo {
    /// Create a new AC adapter object from data from the ACPI subsystem.
    ///
    /// # Arguments
    ///
    /// * `path` - The path to the ACPI device.
    pub fn new(path: &path::Path) -> Result<ACAdapterInfo, Box<dyn Error>> {
        let name = String::from(path.file_name().unwrap().to_str().unwrap());
        let status = parse_entry_file(&path.join("online"))?
            .trim()
            .to_lowercase();
        let status = if status == "1" {
            Status::Online
        } else if status == "0" {
            Status::Offline
        } else {
            return Err(Box::new(AcpiError(
                format!("Invalid contents in {}", &name).into(),
            )));
        };

        Ok(ACAdapterInfo {
            name: name,
            status: status,
        })
    }
}