From 481844408d95d0f5a418f2c4a7d89ad014cdbb01 Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Wed, 10 Jul 2024 21:00:51 -0400 Subject: [PATCH] Improve .attribute() parse type ergonomics --- Cargo.toml | 2 +- src/attribute.rs | 2 +- src/basic.rs | 11 +++++++++-- src/entity.rs | 6 +++--- src/hwmon.rs | 16 +++++++++------- src/power_supply.rs | 5 +++-- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4a65e5e..417ae2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sysfuss" -version = "0.3.0" +version = "0.4.0" edition = "2021" authors = ["NGnius (Graham) "] description = "sysfs wrapper for convenience" diff --git a/src/attribute.rs b/src/attribute.rs index c89599b..aa1367d 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -35,7 +35,7 @@ pub trait SysAttributeExt: SysAttribute { } /// read and parse the attribute value - fn parse, E, ENT: crate::SysEntity + ?Sized>(&self, entity: &ENT) -> Result> { + fn parse(&self, entity: &ENT) -> Result::Err>> { let s = self.read_str(entity).map_err(EitherErr2::First)?; T::from_str(s.trim_end_matches('\n')).map_err(EitherErr2::Second) } diff --git a/src/basic.rs b/src/basic.rs index c9998c4..1a5b7b1 100644 --- a/src/basic.rs +++ b/src/basic.rs @@ -5,6 +5,7 @@ use std::io::Result as IoResult; const SYS_CLASS_PATH: &str = "sys/class"; /// Generic entity path with basic functionality +#[derive(PartialEq, Eq)] #[cfg_attr(feature = "derive", derive(Debug, Clone))] pub struct BasicEntityPath { path: PathBuf @@ -73,6 +74,12 @@ impl crate::SysEntityAttributes for BasicEntityPath { } } +impl <'a> crate::SysEntityAttributes<&'a str> for BasicEntityPath { + fn capabilities(&self) -> Vec<&'a str> { + panic!("Cannot read capabilities into &str") + } +} + #[cfg(test)] mod tests { use super::*; @@ -104,7 +111,7 @@ mod tests { "temp1_alarm".to_string(), "temp1_crit".to_string(), ].into_iter()))?.next().expect("Missing any hwmon"); - let attr_value = crate::SysEntityAttributesExt::attribute::(&basic, "name".to_owned()).expect("name capable but also incapable"); + let attr_value = crate::SysEntityAttributesExt::attribute::(&basic, "name".to_owned()).expect("name capable but also incapable"); println!("Attribute ./name = '{}'", attr_value); assert!(attr_value == "nvme"); Ok(()) @@ -125,7 +132,7 @@ mod tests { "dev".to_string(), "uevent".to_string(), ].into_iter()))?.filter(|basic| basic.name().expect("no name").starts_with("card")).next().expect("Missing drm"); - let attr_value = crate::SysEntityAttributesExt::attribute::(&basic, "dev".to_owned()).expect("dev capable but also incapable"); + let attr_value = crate::SysEntityAttributesExt::attribute::(&basic, "dev".to_owned()).expect("dev capable but also incapable"); println!("Attribute ./dev = '{}'", attr_value); assert!(attr_value == expected_dev); Ok(()) diff --git a/src/entity.rs b/src/entity.rs index 5cfee83..ac9948a 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -38,7 +38,7 @@ pub trait SysEntity: AsRef { /// sysfs class entity functionality extension pub trait SysEntityRawExt: SysEntity { /// Get an attribute on the entity - fn attribute, E>(&self, attr: A) -> Result>; + fn attribute(&self, attr: A) -> Result::Err>>; /// Get an attribute by filename in the entity's directory fn attribute_str>(&self, attr: A) -> IoResult; @@ -50,7 +50,7 @@ pub trait SysEntityRawExt: SysEntity { } impl SysEntityRawExt for X { - fn attribute, E>(&self, attr: A) -> Result> { + fn attribute(&self, attr: A) -> Result::Err>> { attr.parse(self) } @@ -82,7 +82,7 @@ pub trait SysEntityAttributesExt: SysEntityAttributes } /// Get an attribute on the entity - fn attribute, E>(&self, attr: A) -> Result> { + fn attribute(&self, attr: A) -> Result::Err>> { attr.parse(self) } diff --git a/src/hwmon.rs b/src/hwmon.rs index 168d273..e499992 100644 --- a/src/hwmon.rs +++ b/src/hwmon.rs @@ -61,6 +61,8 @@ pub enum HwMonAttributeType { Fan, /// Current Curr, + /// Frequency + Freq, } impl HwMonAttributeType { @@ -70,6 +72,7 @@ impl HwMonAttributeType { Self::Temp => "out", Self::Fan => "fan", Self::Curr => "curr", + Self::Freq => "freq", } } @@ -204,7 +207,7 @@ impl HwMonPath { pub(crate) fn name(root: &crate::SysPath, name: &str) -> IoResult> { for entry in Self::all(root)? { let entry = entry?; - let value: String = entry.attribute::(HwMonAttribute::name()).map_err(|e| match e { + let value: String = entry.attribute::(HwMonAttribute::name()).map_err(|e| match e { crate::EitherErr2::First(e) => e, crate::EitherErr2::Second(_e) => panic!("Infallible"), })?; @@ -269,8 +272,8 @@ mod tests { assert!(!all_hwmon.is_empty()); for hwmon in all_hwmon.into_iter() { let hwmon = hwmon?; - assert!(hwmon.attribute::(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())? != ""); - assert!(!hwmon.attribute::(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())?.ends_with("\n")); + assert!(hwmon.attribute::(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())? != ""); + assert!(!hwmon.attribute::(HwMonAttribute::name()).map_err(|e| e.map_infallible_second())?.ends_with("\n")); assert!(!hwmon.capabilities().is_empty()); assert!(hwmon.capabilities().contains(&HwMonAttribute::name())) } @@ -287,11 +290,10 @@ mod tests { } let hwmon = sys.hwmon(crate::capability::attributes([ HwMonAttribute::name(), - HwMonAttribute::new(HwMonAttributeType::Fan, 1, HwMonAttributeItem::Input), - HwMonAttribute::new(HwMonAttributeType::Fan, 1, HwMonAttributeItem::Min), - HwMonAttribute::new(HwMonAttributeType::Fan, 1, HwMonAttributeItem::Max) + HwMonAttribute::new(HwMonAttributeType::In, 0, HwMonAttributeItem::Input), + HwMonAttribute::new(HwMonAttributeType::In, 0, HwMonAttributeItem::Label), ].into_iter()))?.next().expect("Missing capable amdgpu"); - assert_eq!(hwmon.attribute::(HwMonAttribute::name()).expect("name capable but also incapable"), "amdgpu"); + assert_eq!(hwmon.attribute::(HwMonAttribute::name()).expect("name capable but also incapable"), "amdgpu"); Ok(()) } } diff --git a/src/power_supply.rs b/src/power_supply.rs index 3184733..4a72ae2 100644 --- a/src/power_supply.rs +++ b/src/power_supply.rs @@ -197,6 +197,7 @@ impl std::str::FromStr for PowerSupplyType { } /// power_supply// directory +#[derive(PartialEq, Eq)] #[cfg_attr(feature = "derive", derive(Debug, Clone))] pub struct PowerSupplyPath { inner: crate::BasicEntityPath, @@ -293,7 +294,7 @@ mod tests { use super::*; use crate::SysEntityAttributes; use crate::SysEntityAttributesExt; - use crate::SysAttribute; + use crate::SysAttributeExt; #[test] fn power_supply_all() -> std::io::Result<()> { @@ -325,7 +326,7 @@ mod tests { PowerSupplyAttribute::Type, PowerSupplyAttribute::Capacity, ].into_iter()))?.next().expect("Missing capable battery"); - assert!(psu.attribute::(PowerSupplyAttribute::Type).expect("type capable but also incapable") == PowerSupplyType::Battery); + assert!(psu.attribute::(PowerSupplyAttribute::Type).expect("type capable but also incapable") == PowerSupplyType::Battery); Ok(()) } }