sysinfo/common/
component.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::{ComponentInner, ComponentsInner};
4
5/// Interacting with components.
6///
7/// ```no_run
8/// use sysinfo::Components;
9///
10/// let components = Components::new_with_refreshed_list();
11/// for component in &components {
12///     println!("{component:?}");
13/// }
14/// ```
15pub struct Components {
16    pub(crate) inner: ComponentsInner,
17}
18
19impl Default for Components {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25impl From<Components> for Vec<Component> {
26    fn from(components: Components) -> Self {
27        components.inner.into_vec()
28    }
29}
30
31impl From<Vec<Component>> for Components {
32    fn from(components: Vec<Component>) -> Self {
33        Self {
34            inner: ComponentsInner::from_vec(components),
35        }
36    }
37}
38
39impl std::ops::Deref for Components {
40    type Target = [Component];
41
42    fn deref(&self) -> &Self::Target {
43        self.list()
44    }
45}
46
47impl std::ops::DerefMut for Components {
48    fn deref_mut(&mut self) -> &mut Self::Target {
49        self.list_mut()
50    }
51}
52
53impl<'a> IntoIterator for &'a Components {
54    type Item = &'a Component;
55    type IntoIter = std::slice::Iter<'a, Component>;
56
57    fn into_iter(self) -> Self::IntoIter {
58        self.list().iter()
59    }
60}
61
62impl<'a> IntoIterator for &'a mut Components {
63    type Item = &'a mut Component;
64    type IntoIter = std::slice::IterMut<'a, Component>;
65
66    fn into_iter(self) -> Self::IntoIter {
67        self.list_mut().iter_mut()
68    }
69}
70
71impl Components {
72    /// Creates a new empty [`Components`][crate::Components] type.
73    ///
74    /// If you want it to be filled directly, take a look at
75    /// [`Components::new_with_refreshed_list`].
76    ///
77    /// ```no_run
78    /// use sysinfo::Components;
79    ///
80    /// let mut components = Components::new();
81    /// components.refresh(false);
82    /// for component in &components {
83    ///     println!("{component:?}");
84    /// }
85    /// ```
86    pub fn new() -> Self {
87        Self {
88            inner: ComponentsInner::new(),
89        }
90    }
91
92    /// Creates a new [`Components`][crate::Components] type with the components list
93    /// loaded.
94    ///
95    /// ```no_run
96    /// use sysinfo::Components;
97    ///
98    /// let mut components = Components::new_with_refreshed_list();
99    /// for component in components.list() {
100    ///     println!("{component:?}");
101    /// }
102    /// ```
103    pub fn new_with_refreshed_list() -> Self {
104        let mut components = Self::new();
105        components.refresh(true);
106        components
107    }
108
109    /// Returns the components list.
110    ///
111    /// ```no_run
112    /// use sysinfo::Components;
113    ///
114    /// let components = Components::new_with_refreshed_list();
115    /// for component in components.list() {
116    ///     println!("{component:?}");
117    /// }
118    /// ```
119    pub fn list(&self) -> &[Component] {
120        self.inner.list()
121    }
122
123    /// Returns the components list.
124    ///
125    /// ```no_run
126    /// use sysinfo::Components;
127    ///
128    /// let mut components = Components::new_with_refreshed_list();
129    /// for component in components.list_mut() {
130    ///     component.refresh();
131    ///     println!("{component:?}");
132    /// }
133    /// ```
134    pub fn list_mut(&mut self) -> &mut [Component] {
135        self.inner.list_mut()
136    }
137
138    /// Refreshes the components list.
139    ///
140    /// ```no_run
141    /// use sysinfo::Components;
142    ///
143    /// let mut components = Components::new_with_refreshed_list();
144    /// // We wait some time...?
145    /// components.refresh(false);
146    /// ```
147    pub fn refresh(&mut self, remove_not_listed_components: bool) {
148        self.inner.refresh();
149        if remove_not_listed_components {
150            // Remove interfaces which are gone.
151            self.inner.components.retain_mut(|c| {
152                if !c.inner.updated {
153                    return false;
154                }
155                c.inner.updated = false;
156                true
157            });
158        }
159    }
160}
161
162/// Getting a component temperature information.
163///
164/// ```no_run
165/// use sysinfo::Components;
166///
167/// let components = Components::new_with_refreshed_list();
168/// for component in &components {
169///     if let Some(temperature) = component.temperature() {
170///         println!("{} {temperature}°C", component.label());
171///     } else {
172///         println!("{} (unknown temperature)", component.label());
173///     }
174/// }
175/// ```
176pub struct Component {
177    pub(crate) inner: ComponentInner,
178}
179
180impl Component {
181    /// Returns the temperature of the component (in celsius degree).
182    ///
183    /// ## Linux
184    ///
185    /// Returns `f32::NAN` if it failed to retrieve it.
186    ///
187    /// ```no_run
188    /// use sysinfo::Components;
189    ///
190    /// let components = Components::new_with_refreshed_list();
191    /// for component in &components {
192    ///     if let Some(temperature) = component.temperature() {
193    ///         println!("{temperature}°C");
194    ///     }
195    /// }
196    /// ```
197    pub fn temperature(&self) -> Option<f32> {
198        self.inner.temperature()
199    }
200
201    /// Returns the maximum temperature of the component (in celsius degree).
202    ///
203    /// Note: if `temperature` is higher than the current `max`,
204    /// `max` value will be updated on refresh.
205    ///
206    /// ## Linux
207    ///
208    /// May be computed by `sysinfo` from kernel.
209    /// Returns `f32::NAN` if it failed to retrieve it.
210    ///
211    /// ```no_run
212    /// use sysinfo::Components;
213    ///
214    /// let components = Components::new_with_refreshed_list();
215    /// for component in &components {
216    ///     if let Some(max) = component.max() {
217    ///         println!("{max}°C");
218    ///     }
219    /// }
220    /// ```
221    pub fn max(&self) -> Option<f32> {
222        self.inner.max()
223    }
224
225    /// Returns the highest temperature before the component halts (in celsius degree).
226    ///
227    /// ## Linux
228    ///
229    /// Critical threshold defined by chip or kernel.
230    ///
231    /// ```no_run
232    /// use sysinfo::Components;
233    ///
234    /// let components = Components::new_with_refreshed_list();
235    /// for component in &components {
236    ///     if let Some(critical) = component.critical() {
237    ///         println!("{critical}°C");
238    ///     }
239    /// }
240    /// ```
241    pub fn critical(&self) -> Option<f32> {
242        self.inner.critical()
243    }
244
245    /// Returns the label of the component.
246    ///
247    /// ## Linux
248    ///
249    /// Since components information is retrieved thanks to `hwmon`,
250    /// the labels are generated as follows.
251    /// Note: it may change and it was inspired by `sensors` own formatting.
252    ///
253    /// | name | label | device_model | id_sensor | Computed label by `sysinfo` |
254    /// |---------|--------|------------|----------|----------------------|
255    /// | ✓    | ✓    | ✓  | ✓ | `"{name} {label} {device_model}"` |
256    /// | ✓    | ✓    | ✗  | ✓ | `"{name} {label}"` |
257    /// | ✓    | ✗    | ✓  | ✓ | `"{name} {device_model}"` |
258    /// | ✓    | ✗    | ✗  | ✓ | `"{name} temp{id}"` |
259    ///
260    /// ```no_run
261    /// use sysinfo::Components;
262    ///
263    /// let components = Components::new_with_refreshed_list();
264    /// for component in &components {
265    ///     println!("{}", component.label());
266    /// }
267    /// ```
268    pub fn label(&self) -> &str {
269        self.inner.label()
270    }
271
272    /// Refreshes component.
273    ///
274    /// ```no_run
275    /// use sysinfo::Components;
276    ///
277    /// let mut components = Components::new_with_refreshed_list();
278    /// for component in components.iter_mut() {
279    ///     component.refresh();
280    /// }
281    /// ```
282    pub fn refresh(&mut self) {
283        self.inner.refresh()
284    }
285}
286
287#[cfg(test)]
288mod tests {
289    use crate::*;
290
291    #[test]
292    fn test_components_mac_m1() {
293        let mut components = Components::new();
294        components.refresh(false);
295        components.refresh(false);
296    }
297}