sysfuss 0.3.0

sysfs wrapper for convenience
Documentation
use std::path::PathBuf;
use std::io::Result as IoResult;
use std::str::FromStr;

use crate::EitherErr2;

/// sysfs entity attribute file functionality
pub trait SysAttribute: Eq {
    /// attribute file name
    fn filename(&self) -> PathBuf;
}

impl SysAttribute for String {
    fn filename(&self) -> PathBuf {
        PathBuf::from(self)
    }
}

impl SysAttribute for &str {
    fn filename(&self) -> PathBuf {
        PathBuf::from(self)
    }
}

/// sysfs entity attribute functionality extension
pub trait SysAttributeExt: SysAttribute {
    /// read attribute as string
    fn read_str<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> IoResult<String> {
        std::fs::read_to_string(self.path(entity))
    }
    
    /// write attribute string value to sysfsfilter_map
    fn write_str<E: crate::SysEntity + ?Sized>(&self, entity: &E, s: &str) -> IoResult<()> {
        std::fs::write(self.path(entity), s.as_bytes())
    }
    
    /// read and parse the attribute value
    fn parse<T: FromStr<Err=E>, E, ENT: crate::SysEntity + ?Sized>(&self, entity: &ENT) -> Result<T, EitherErr2<std::io::Error, E>> {
        let s = self.read_str(entity).map_err(EitherErr2::First)?;
        T::from_str(s.trim_end_matches('\n')).map_err(EitherErr2::Second)
    }

    /// full path to attribute file
    fn path<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> PathBuf {
        entity.as_ref().join(self.filename())
    }

    /// returns true if the path to the attribute file exists
    fn exists<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> bool {
        let path = self.path(entity);
        path.exists() && path.is_file()
    }

    /// read attribute value from sysfs
    fn read_value<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> IoResult<Vec<u8>> {
        std::fs::read(self.path(entity))
    }

    /// write attribute value to sysfs
    fn write_value<E: crate::SysEntity + ?Sized>(&self, entity: &E, value: &[u8]) -> IoResult<()> {
        std::fs::write(self.path(entity), value)
    }

    /// Returns true if the attribute is readonly
    fn readonly<E: crate::SysEntity + ?Sized>(&self, entity: &E) -> bool {
        self.path(entity).metadata().map(|meta| meta.permissions().readonly()).unwrap_or(false)
    }
}

impl <X: SysAttribute + Eq> SysAttributeExt for X {}