lm_sensors/
sub_feature.rs1#[cfg(test)]
5mod tests;
6
7use core::ffi::CStr;
8use core::ffi::{c_int, c_uint};
9use core::fmt;
10use std::io;
11
12use bitflags::bitflags;
13use sensors_sys::{
14 SENSORS_COMPUTE_MAPPING, SENSORS_MODE_R, SENSORS_MODE_W, sensors_get_all_subfeatures,
15 sensors_get_value, sensors_set_value, sensors_subfeature,
16};
17
18use crate::errors::{Error, Result};
19use crate::feature::FeatureRef;
20use crate::utils::API_ACCESS_LOCK;
21use crate::value::{Kind, Value};
22
23#[derive(Debug, Clone, Copy, Eq)]
28pub struct SubFeatureRef<'sensors> {
29 pub(crate) feature: FeatureRef<'sensors>,
30 pub(crate) raw: &'sensors sensors_subfeature,
31}
32
33impl<'sensors> SubFeatureRef<'sensors> {
34 #[must_use]
36 pub fn raw_ref(self) -> &'sensors sensors_subfeature {
37 self.raw
38 }
39
40 #[must_use]
42 pub fn feature(self) -> FeatureRef<'sensors> {
43 self.feature
44 }
45
46 #[must_use]
51 pub fn name(self) -> Option<Result<&'sensors str>> {
52 self.raw_name()
53 .map(|name| name.to_str().map_err(Into::into))
54 }
55
56 #[must_use]
58 pub fn number(self) -> c_int {
59 self.raw.number
60 }
61
62 #[must_use]
64 pub fn mapping(self) -> c_int {
65 self.raw.mapping
66 }
67
68 #[must_use]
70 pub fn kind(self) -> Option<Kind> {
71 Kind::from_raw(self.raw_kind())
72 }
73
74 #[must_use]
76 pub fn flags(self) -> Option<Flags> {
77 Flags::from_bits(self.raw_flags())
78 }
79
80 pub fn value(self) -> Result<Value> {
82 let value = self.raw_value()?;
83 Value::from_raw(self.raw_kind(), value)
84 .ok_or_else(|| Error::from_io("Value::from_raw", io::ErrorKind::InvalidData.into()))
85 }
86
87 pub fn set_value(self, new_value: &Value) -> Result<()> {
89 self.set_raw_value(new_value.raw_value())
90 }
91
92 #[must_use]
94 pub fn raw_name(self) -> Option<&'sensors CStr> {
95 (!self.raw.name.is_null()).then(|| unsafe { CStr::from_ptr(self.raw.name) })
97 }
98
99 #[must_use]
104 pub fn raw_kind(self) -> c_uint {
105 self.raw.type_
106 }
107
108 #[must_use]
111 pub fn raw_flags(self) -> c_uint {
112 self.raw.flags
113 }
114
115 pub fn raw_value(self) -> Result<f64> {
119 let mut result = 0.0_f64;
120
121 let r = {
122 let _guard = API_ACCESS_LOCK.lock();
123 unsafe { sensors_get_value(self.feature.chip.raw_ref(), self.number(), &mut result) }
125 };
126
127 if r == 0 {
128 Ok(result)
129 } else {
130 Err(Error::from_lm_sensors("sensors_get_value()", r))
131 }
132 }
133
134 pub fn set_raw_value(self, new_value: f64) -> Result<()> {
138 let chip = self.feature.chip.raw_ref();
139 let number = self.number();
140 let r = {
141 let _guard = API_ACCESS_LOCK.lock();
142 unsafe { sensors_set_value(chip, number, new_value) }
144 };
145
146 if r == 0 {
147 Ok(())
148 } else {
149 Err(Error::from_lm_sensors("sensors_set_value()", r))
150 }
151 }
152}
153
154impl PartialEq for SubFeatureRef<'_> {
155 fn eq(&self, other: &Self) -> bool {
156 self.feature == other.feature
157 && self.number() == other.number()
158 && self.mapping() == other.mapping()
159 && self.raw_kind() == other.raw_kind()
160 && self.raw_flags() == other.raw_flags()
161 && self.raw_name() == other.raw_name()
162 }
163}
164
165impl fmt::Display for SubFeatureRef<'_> {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 if let Some(name) = self.raw_name() {
168 write!(f, "{}", name.to_string_lossy())
169 } else {
170 Ok(())
171 }
172 }
173}
174
175bitflags! {
176 #[repr(transparent)]
178 pub struct Flags: c_uint {
179 #[allow(clippy::as_conversions)]
181 const READABLE = SENSORS_MODE_R as c_uint;
182
183 #[allow(clippy::as_conversions)]
185 const WRITABLE = SENSORS_MODE_W as c_uint;
186
187 #[allow(clippy::as_conversions)]
190 const COMPUTE_MAPPING = SENSORS_COMPUTE_MAPPING as c_uint;
191 }
192}
193
194#[derive(Debug)]
196#[must_use]
197pub struct Iter<'sensors> {
198 pub(crate) feature: FeatureRef<'sensors>,
199 pub(crate) state: c_int,
200}
201
202impl<'sensors> Iterator for Iter<'sensors> {
203 type Item = SubFeatureRef<'sensors>;
204
205 fn next(&mut self) -> Option<Self::Item> {
207 let subfeature = {
208 let _guard = API_ACCESS_LOCK.lock();
209 unsafe {
211 sensors_get_all_subfeatures(
212 self.feature.chip.raw_ref(),
213 self.feature.raw,
214 &mut self.state,
215 )
216 .as_ref()
217 }
218 };
219
220 subfeature.map(|raw| SubFeatureRef {
221 feature: self.feature,
222 raw,
223 })
224 }
225}