sysfuss 0.3.0

sysfs wrapper for convenience
Documentation
use std::path::{Path, PathBuf};
use std::convert::AsRef;

use crate::SysEntity;

/// sysfs root
#[cfg_attr(feature = "derive", derive(Debug))]
pub struct SysPath {
    root: PathBuf,
}

impl SysPath {
    /// Initialize with a custom root.
    /// Use SysPath::default() to use the default root `/`.
    pub fn path(root: impl AsRef<Path>) -> Self {
        Self {
            root: root.as_ref().to_path_buf()
        }
    }
    
    /// Get all entities in the system
    pub fn entities(&self) -> std::io::Result<impl Iterator<Item=std::io::Result<crate::EntityPath>> + '_> {
        Ok(crate::HwMonPath::all(self)?
            .map(|entity| entity.map(|entity| entity.to_entity_path()))
            .chain(crate::PowerSupplyPath::all(self)?
                .map(|entity| entity.map(|entity| entity.to_entity_path()))))
    }
    
    /// Find a hardware monitor entry by name
    pub fn hwmon_by_name(&self, name: &str) -> std::io::Result<crate::HwMonPath> {
        match crate::HwMonPath::name(self, name) {
            Ok(None) => Err(std::io::Error::from_raw_os_error(std::io::ErrorKind::NotFound as _)),
            Ok(Some(x)) => Ok(x),
            Err(e) => Err(e)
        }
    }
    
    /// Find a hardware monitor entry by index
    pub fn hwmon_by_index(&self, index: u64) -> crate::HwMonPath {
        let entry = crate::HwMonPath::entry(self, index);
        //entry.attribute(crate::HwMonAttribute::name())?;
        entry
    }

    /// Find a hardware monitor by capabilities
    pub fn hwmon(&self, mut c: impl crate::capability::Capabilities<crate::HwMonAttribute, crate::HwMonPath>) -> std::io::Result<impl Iterator<Item=crate::HwMonPath>> {
        Ok(crate::HwMonPath::all(self.root.clone())?
            .filter_map(|p| p.ok())
            .filter(move |p| c.satisfies(p)))
    }
    
    /// Find a power supply entry by name
    pub fn power_supply_by_name(&self, name: &str) -> crate::PowerSupplyPath {
        crate::PowerSupplyPath::name(self, name)
    }

    /// Find a power supply by capabilities
    pub fn power_supply(&self, mut c: impl crate::capability::Capabilities<crate::PowerSupplyAttribute, crate::PowerSupplyPath>) -> std::io::Result<impl Iterator<Item=crate::PowerSupplyPath>> {
        Ok(crate::PowerSupplyPath::all(self.root.clone())?
            .filter_map(|p| p.ok())
            .filter(move |p| c.satisfies(p)))
    }

    /// Find entities in a sysfs class by capabilities
    pub fn class(&self, class: impl AsRef<Path>, mut c: impl crate::capability::Capabilities<String, crate::BasicEntityPath>) -> std::io::Result<impl Iterator<Item=crate::BasicEntityPath>> {
        Ok(crate::BasicEntityPath::all(self.root.clone(), class)?
            .filter_map(|p| p.ok())
            .filter(move |p| c.satisfies(p)))
    }

    pub(crate) fn from_entity_path(entity: impl AsRef<Path>) -> Option<Self> {
        Some(Self::path(entity.as_ref().parent()?.parent()?.parent()?.parent()?))
    }
}

impl std::default::Default for SysPath {
    fn default() -> Self {
        Self {
            root: PathBuf::from(crate::DEFAULT_ROOT)
        }
    }
}

impl AsRef<Path> for SysPath {
    fn as_ref(&self) -> &Path {
        self.root.as_path()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::SysEntity;

    #[test]
    fn syspath_root_recovery() -> std::io::Result<()> {
        let sys = crate::SysPath::default();
        let all_ent: Vec<_> = crate::BasicEntityPath::all(&sys, "hwmon")?.collect();
        assert!(!all_ent.is_empty());
        for p in all_ent.into_iter() {
            let p = p?;
            let root_opt = p.root();
            assert!(root_opt.is_some());
            assert_eq!(sys.as_ref(), root_opt.unwrap().as_ref());
        }
        Ok(())
    }
}