Add more capability functionality and improve API

This commit is contained in:
NGnius (Graham) 2023-08-06 14:50:34 -04:00
parent 16f32e7e9d
commit 65eae75c3a
5 changed files with 58 additions and 3 deletions

View file

@ -63,7 +63,7 @@ pub trait SysAttributeExt: SysAttribute + Eq {
/// read and parse the attribute value /// read and parse the attribute value
fn parse<T: FromStr<Err=E>, E>(&self, entity: &dyn crate::SysEntity) -> Result<T, EitherErr2<std::io::Error, E>> { fn parse<T: FromStr<Err=E>, E>(&self, entity: &dyn crate::SysEntity) -> Result<T, EitherErr2<std::io::Error, E>> {
let s = self.read_str(entity).map_err(EitherErr2::First)?; let s = self.read_str(entity).map_err(EitherErr2::First)?;
T::from_str(&s).map_err(EitherErr2::Second) T::from_str(s.trim_end_matches('\n')).map_err(EitherErr2::Second)
} }
} }

View file

@ -19,6 +19,12 @@ pub fn attributes<'a, A: crate::SysAttribute + Eq + 'a, R: std::borrow::Borrow<A
) )
} }
/// Build a Capabilities implementor which needs specific functions to evaluate to true for some attribute
pub fn complex<'a, A: crate::SysAttribute + 'a, R: std::borrow::Borrow<A> + 'a, F: (FnMut(&R) -> bool) + 'a>(requirements: impl Iterator<Item=F>) -> impl Capabilities<A, R> + 'a {
AllNeedsCapabilities::new(
requirements.collect()
)
}
struct AllNeedsCapabilities<'a, 'f, A: crate::SysAttribute + 'a, R: std::borrow::Borrow<A> + 'a, F: (FnMut(&R) -> bool) + 'f> { struct AllNeedsCapabilities<'a, 'f, A: crate::SysAttribute + 'a, R: std::borrow::Borrow<A> + 'a, F: (FnMut(&R) -> bool) + 'f> {
wanted: Vec<F>, wanted: Vec<F>,
@ -51,3 +57,32 @@ impl <'a, 'f, A: crate::SysAttribute + 'a, R: std::borrow::Borrow<A> + 'a, F: (F
wants.into_iter().all(|item| item) wants.into_iter().all(|item| item)
} }
} }
/// Chain two capabilities requirements together such that the new capabilities are only satisfied when both inner capabilities are satisfied
pub fn and<A: crate::SysAttribute, R: std::borrow::Borrow<A>>(first: impl Capabilities<A, R>, second: impl Capabilities<A, R>) -> impl Capabilities<A, R> {
ChainCapabilities::new(first, second)
}
struct ChainCapabilities<A: crate::SysAttribute, R: std::borrow::Borrow<A>, X: Capabilities<A, R>, Y: Capabilities<A, R>> {
first: X,
second: Y,
_attr_ty: std::marker::PhantomData<A>,
_attr_brw_ty: std::marker::PhantomData<R>,
}
impl <A: crate::SysAttribute, R: std::borrow::Borrow<A>, X: Capabilities<A, R>, Y: Capabilities<A, R>> ChainCapabilities<A, R, X, Y> {
pub(crate) fn new(first: X, second: Y) -> Self {
Self {
first,
second,
_attr_ty: Default::default(),
_attr_brw_ty: Default::default(),
}
}
}
impl <A: crate::SysAttribute, R: std::borrow::Borrow<A>, X: Capabilities<A, R>, Y: Capabilities<A, R>> Capabilities<A, R> for ChainCapabilities<A, R, X, Y> {
fn can(&mut self, capabilities: &Vec<R>) -> bool {
self.first.can(capabilities) && self.second.can(capabilities)
}
}

View file

@ -72,9 +72,21 @@ impl <X: SysEntity> SysEntityRawExt for X {
pub trait SysEntityAttributes<A: crate::SysAttribute + Eq>: SysEntity + Sized { pub trait SysEntityAttributes<A: crate::SysAttribute + Eq>: SysEntity + Sized {
/// Get attributes available on this entity; /// Get attributes available on this entity;
fn capabilities(&self) -> Vec<A>; fn capabilities(&self) -> Vec<A>;
/// Read entity attribute value
fn read_value(&self, attr: A) -> IoResult<Vec<u8>> {
attr.read_value(self)
} }
/// Write entity attribute value
fn write_value(&self, attr: A, value: &[u8]) -> IoResult<()> {
attr.write_value(self, value)
}
}
/// sysfs class entity attribute type extension
pub trait SysEntityAttributesExt<A: crate::SysAttribute + Eq>: SysEntityAttributes<A> { pub trait SysEntityAttributesExt<A: crate::SysAttribute + Eq>: SysEntityAttributes<A> {
/// Returns true if self is capable of the provided capabilities
fn capable<C: crate::capability::Capabilities<A, A>>(&self, mut capabilities: C) -> bool { fn capable<C: crate::capability::Capabilities<A, A>>(&self, mut capabilities: C) -> bool {
capabilities.can(&self.capabilities()) capabilities.can(&self.capabilities())
} }
@ -83,6 +95,11 @@ pub trait SysEntityAttributesExt<A: crate::SysAttribute + Eq>: SysEntityAttribut
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<Err=E>, E>(&self, attr: A) -> Result<T, EitherErr2<std::io::Error, E>> {
attr.parse(self) attr.parse(self)
} }
/// Set an attribute on the entity
fn set<V: std::string::ToString>(&self, attr: A, value: V) -> IoResult<()> {
attr.write_str(self, &value.to_string())
}
} }
impl <A: crate::SysAttribute + Eq, X: SysEntityAttributes<A>> SysEntityAttributesExt<A> for X {} impl <A: crate::SysAttribute + Eq, X: SysEntityAttributes<A>> SysEntityAttributesExt<A> for X {}

View file

@ -96,6 +96,8 @@ pub enum HwMonAttributeItem {
Min, Min,
/// Maximum /// Maximum
Max, Max,
/// Readable name for another attribute
Label,
} }
impl HwMonAttributeItem { impl HwMonAttributeItem {
@ -104,6 +106,7 @@ impl HwMonAttributeItem {
Self::Input => "input", Self::Input => "input",
Self::Min => "min", Self::Min => "min",
Self::Max => "max", Self::Max => "max",
Self::Label => "label"
} }
} }
@ -213,7 +216,7 @@ impl HwMonPath {
} }
/// Get a hwmon attribute (file contents) /// Get a hwmon attribute (file contents)
pub fn attribute(&self, attr: HwMonAttribute) -> IoResult<String> { fn attribute(&self, attr: HwMonAttribute) -> IoResult<String> {
self.attribute_str(&attr.to_attr_str()) self.attribute_str(&attr.to_attr_str())
} }

View file

@ -13,7 +13,7 @@ pub use basic::BasicEntityPath;
pub mod capability; pub mod capability;
mod entity; mod entity;
pub use entity::{EntityPath, SysEntity, SysEntityRawExt, SysEntityAttributes}; pub use entity::{EntityPath, SysEntity, SysEntityRawExt, SysEntityAttributes, SysEntityAttributesExt};
mod errors; mod errors;
pub use errors::{EitherErr2, ValueEnumError}; pub use errors::{EitherErr2, ValueEnumError};