Improve .attribute() parse type ergonomics
This commit is contained in:
parent
942d9f71e5
commit
481844408d
6 changed files with 26 additions and 16 deletions
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "sysfuss"
|
name = "sysfuss"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
|
authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
|
||||||
description = "sysfs wrapper for convenience"
|
description = "sysfs wrapper for convenience"
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub trait SysAttributeExt: SysAttribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// read and parse the attribute value
|
/// 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>> {
|
fn parse<T: FromStr, ENT: crate::SysEntity + ?Sized>(&self, entity: &ENT) -> Result<T, EitherErr2<std::io::Error, <T as FromStr>::Err>> {
|
||||||
let s = self.read_str(entity).map_err(EitherErr2::First)?;
|
let s = self.read_str(entity).map_err(EitherErr2::First)?;
|
||||||
T::from_str(s.trim_end_matches('\n')).map_err(EitherErr2::Second)
|
T::from_str(s.trim_end_matches('\n')).map_err(EitherErr2::Second)
|
||||||
}
|
}
|
||||||
|
|
11
src/basic.rs
11
src/basic.rs
|
@ -5,6 +5,7 @@ use std::io::Result as IoResult;
|
||||||
const SYS_CLASS_PATH: &str = "sys/class";
|
const SYS_CLASS_PATH: &str = "sys/class";
|
||||||
|
|
||||||
/// Generic entity path with basic functionality
|
/// Generic entity path with basic functionality
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "derive", derive(Debug, Clone))]
|
#[cfg_attr(feature = "derive", derive(Debug, Clone))]
|
||||||
pub struct BasicEntityPath {
|
pub struct BasicEntityPath {
|
||||||
path: PathBuf
|
path: PathBuf
|
||||||
|
@ -73,6 +74,12 @@ impl crate::SysEntityAttributes<String> for BasicEntityPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <'a> crate::SysEntityAttributes<&'a str> for BasicEntityPath {
|
||||||
|
fn capabilities(&self) -> Vec<&'a str> {
|
||||||
|
panic!("Cannot read capabilities into &str")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -104,7 +111,7 @@ mod tests {
|
||||||
"temp1_alarm".to_string(),
|
"temp1_alarm".to_string(),
|
||||||
"temp1_crit".to_string(),
|
"temp1_crit".to_string(),
|
||||||
].into_iter()))?.next().expect("Missing any hwmon");
|
].into_iter()))?.next().expect("Missing any hwmon");
|
||||||
let attr_value = crate::SysEntityAttributesExt::attribute::<String, _>(&basic, "name".to_owned()).expect("name capable but also incapable");
|
let attr_value = crate::SysEntityAttributesExt::attribute::<String>(&basic, "name".to_owned()).expect("name capable but also incapable");
|
||||||
println!("Attribute ./name = '{}'", attr_value);
|
println!("Attribute ./name = '{}'", attr_value);
|
||||||
assert!(attr_value == "nvme");
|
assert!(attr_value == "nvme");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -125,7 +132,7 @@ mod tests {
|
||||||
"dev".to_string(),
|
"dev".to_string(),
|
||||||
"uevent".to_string(),
|
"uevent".to_string(),
|
||||||
].into_iter()))?.filter(|basic| basic.name().expect("no name").starts_with("card")).next().expect("Missing drm");
|
].into_iter()))?.filter(|basic| basic.name().expect("no name").starts_with("card")).next().expect("Missing drm");
|
||||||
let attr_value = crate::SysEntityAttributesExt::attribute::<String, _>(&basic, "dev".to_owned()).expect("dev capable but also incapable");
|
let attr_value = crate::SysEntityAttributesExt::attribute::<String>(&basic, "dev".to_owned()).expect("dev capable but also incapable");
|
||||||
println!("Attribute ./dev = '{}'", attr_value);
|
println!("Attribute ./dev = '{}'", attr_value);
|
||||||
assert!(attr_value == expected_dev);
|
assert!(attr_value == expected_dev);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub trait SysEntity: AsRef<Path> {
|
||||||
/// sysfs class entity functionality extension
|
/// sysfs class entity functionality extension
|
||||||
pub trait SysEntityRawExt: SysEntity {
|
pub trait SysEntityRawExt: SysEntity {
|
||||||
/// Get an attribute on the entity
|
/// Get an attribute on the entity
|
||||||
fn attribute<A: crate::SysAttribute, T: std::str::FromStr<Err=E>, E>(&self, attr: A) -> Result<T, EitherErr2<std::io::Error, E>>;
|
fn attribute<A: crate::SysAttribute, T: std::str::FromStr>(&self, attr: A) -> Result<T, EitherErr2<std::io::Error, <T as std::str::FromStr>::Err>>;
|
||||||
/// Get an attribute by filename in the entity's directory
|
/// Get an attribute by filename in the entity's directory
|
||||||
fn attribute_str<A: AsRef<Path>>(&self, attr: A) -> IoResult<String>;
|
fn attribute_str<A: AsRef<Path>>(&self, attr: A) -> IoResult<String>;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ pub trait SysEntityRawExt: SysEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <X: SysEntity> SysEntityRawExt for X {
|
impl <X: SysEntity> SysEntityRawExt for X {
|
||||||
fn attribute<A: crate::SysAttribute, T: std::str::FromStr<Err=E>, E>(&self, attr: A) -> Result<T, EitherErr2<std::io::Error, E>> {
|
fn attribute<A: crate::SysAttribute, T: std::str::FromStr>(&self, attr: A) -> Result<T, EitherErr2<std::io::Error, <T as std::str::FromStr>::Err>> {
|
||||||
attr.parse(self)
|
attr.parse(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ pub trait SysEntityAttributesExt<A: crate::SysAttribute>: SysEntityAttributes<A>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an attribute on the entity
|
/// Get an attribute on the entity
|
||||||
fn attribute<T: std::str::FromStr<Err=E>, E>(&self, attr: A) -> Result<T, EitherErr2<std::io::Error, E>> {
|
fn attribute<T: std::str::FromStr>(&self, attr: A) -> Result<T, EitherErr2<std::io::Error, <T as std::str::FromStr>::Err>> {
|
||||||
attr.parse(self)
|
attr.parse(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
src/hwmon.rs
16
src/hwmon.rs
|
@ -61,6 +61,8 @@ pub enum HwMonAttributeType {
|
||||||
Fan,
|
Fan,
|
||||||
/// Current
|
/// Current
|
||||||
Curr,
|
Curr,
|
||||||
|
/// Frequency
|
||||||
|
Freq,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HwMonAttributeType {
|
impl HwMonAttributeType {
|
||||||
|
@ -70,6 +72,7 @@ impl HwMonAttributeType {
|
||||||
Self::Temp => "out",
|
Self::Temp => "out",
|
||||||
Self::Fan => "fan",
|
Self::Fan => "fan",
|
||||||
Self::Curr => "curr",
|
Self::Curr => "curr",
|
||||||
|
Self::Freq => "freq",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +207,7 @@ impl HwMonPath {
|
||||||
pub(crate) fn name(root: &crate::SysPath, name: &str) -> IoResult<Option<Self>> {
|
pub(crate) fn name(root: &crate::SysPath, name: &str) -> IoResult<Option<Self>> {
|
||||||
for entry in Self::all(root)? {
|
for entry in Self::all(root)? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let value: String = entry.attribute::<String, _>(HwMonAttribute::name()).map_err(|e| match e {
|
let value: String = entry.attribute::<String>(HwMonAttribute::name()).map_err(|e| match e {
|
||||||
crate::EitherErr2::First(e) => e,
|
crate::EitherErr2::First(e) => e,
|
||||||
crate::EitherErr2::Second(_e) => panic!("Infallible"),
|
crate::EitherErr2::Second(_e) => panic!("Infallible"),
|
||||||
})?;
|
})?;
|
||||||
|
@ -269,8 +272,8 @@ mod tests {
|
||||||
assert!(!all_hwmon.is_empty());
|
assert!(!all_hwmon.is_empty());
|
||||||
for hwmon in all_hwmon.into_iter() {
|
for hwmon in all_hwmon.into_iter() {
|
||||||
let hwmon = hwmon?;
|
let hwmon = hwmon?;
|
||||||
assert!(hwmon.attribute::<String, _>(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())? != "");
|
assert!(hwmon.attribute::<String>(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())? != "");
|
||||||
assert!(!hwmon.attribute::<String, _>(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())?.ends_with("\n"));
|
assert!(!hwmon.attribute::<String>(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())?.ends_with("\n"));
|
||||||
assert!(!hwmon.capabilities().is_empty());
|
assert!(!hwmon.capabilities().is_empty());
|
||||||
assert!(hwmon.capabilities().contains(&HwMonAttribute::name()))
|
assert!(hwmon.capabilities().contains(&HwMonAttribute::name()))
|
||||||
}
|
}
|
||||||
|
@ -287,11 +290,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
let hwmon = sys.hwmon(crate::capability::attributes([
|
let hwmon = sys.hwmon(crate::capability::attributes([
|
||||||
HwMonAttribute::name(),
|
HwMonAttribute::name(),
|
||||||
HwMonAttribute::new(HwMonAttributeType::Fan, 1, HwMonAttributeItem::Input),
|
HwMonAttribute::new(HwMonAttributeType::In, 0, HwMonAttributeItem::Input),
|
||||||
HwMonAttribute::new(HwMonAttributeType::Fan, 1, HwMonAttributeItem::Min),
|
HwMonAttribute::new(HwMonAttributeType::In, 0, HwMonAttributeItem::Label),
|
||||||
HwMonAttribute::new(HwMonAttributeType::Fan, 1, HwMonAttributeItem::Max)
|
|
||||||
].into_iter()))?.next().expect("Missing capable amdgpu");
|
].into_iter()))?.next().expect("Missing capable amdgpu");
|
||||||
assert_eq!(hwmon.attribute::<String, _>(HwMonAttribute::name()).expect("name capable but also incapable"), "amdgpu");
|
assert_eq!(hwmon.attribute::<String>(HwMonAttribute::name()).expect("name capable but also incapable"), "amdgpu");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,6 +197,7 @@ impl std::str::FromStr for PowerSupplyType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// power_supply/<entity>/ directory
|
/// power_supply/<entity>/ directory
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "derive", derive(Debug, Clone))]
|
#[cfg_attr(feature = "derive", derive(Debug, Clone))]
|
||||||
pub struct PowerSupplyPath {
|
pub struct PowerSupplyPath {
|
||||||
inner: crate::BasicEntityPath,
|
inner: crate::BasicEntityPath,
|
||||||
|
@ -293,7 +294,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::SysEntityAttributes;
|
use crate::SysEntityAttributes;
|
||||||
use crate::SysEntityAttributesExt;
|
use crate::SysEntityAttributesExt;
|
||||||
use crate::SysAttribute;
|
use crate::SysAttributeExt;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn power_supply_all() -> std::io::Result<()> {
|
fn power_supply_all() -> std::io::Result<()> {
|
||||||
|
@ -325,7 +326,7 @@ mod tests {
|
||||||
PowerSupplyAttribute::Type,
|
PowerSupplyAttribute::Type,
|
||||||
PowerSupplyAttribute::Capacity,
|
PowerSupplyAttribute::Capacity,
|
||||||
].into_iter()))?.next().expect("Missing capable battery");
|
].into_iter()))?.next().expect("Missing capable battery");
|
||||||
assert!(psu.attribute::<PowerSupplyType, _>(PowerSupplyAttribute::Type).expect("type capable but also incapable") == PowerSupplyType::Battery);
|
assert!(psu.attribute::<PowerSupplyType>(PowerSupplyAttribute::Type).expect("type capable but also incapable") == PowerSupplyType::Battery);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue