Skip to main content

sysinfo/
serde.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[cfg(any(
4    feature = "component",
5    feature = "disk",
6    feature = "network",
7    feature = "system",
8    feature = "user"
9))]
10use serde::{Serialize, Serializer, ser::SerializeStruct};
11
12#[cfg(feature = "disk")]
13impl Serialize for crate::Disk {
14    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
15    where
16        S: Serializer,
17    {
18        // `7` corresponds to the (maximum) number of fields.
19        let mut state = serializer.serialize_struct("Disk", 7)?;
20
21        state.serialize_field("DiskKind", &self.kind())?;
22        if let Some(s) = self.name().to_str() {
23            state.serialize_field("name", s)?;
24        }
25        state.serialize_field("file_system", &self.file_system().to_string_lossy())?;
26        state.serialize_field("mount_point", &self.mount_point())?;
27        state.serialize_field("total_space", &self.total_space())?;
28        state.serialize_field("available_space", &self.available_space())?;
29        state.serialize_field("is_removable", &self.is_removable())?;
30
31        state.end()
32    }
33}
34
35#[cfg(feature = "disk")]
36impl Serialize for crate::Disks {
37    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38    where
39        S: Serializer,
40    {
41        serializer.collect_seq(self.iter())
42    }
43}
44
45#[cfg(feature = "disk")]
46impl Serialize for crate::DiskKind {
47    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48    where
49        S: Serializer,
50    {
51        let (index, variant, maybe_value) = match *self {
52            Self::HDD => (0, "HDD", None),
53            Self::SSD => (1, "SSD", None),
54            Self::Unknown(ref s) => (2, "Unknown", Some(s)),
55        };
56
57        if let Some(ref value) = maybe_value {
58            serializer.serialize_newtype_variant("DiskKind", index, variant, value)
59        } else {
60            serializer.serialize_unit_variant("DiskKind", index, variant)
61        }
62    }
63}
64
65#[cfg(feature = "system")]
66impl Serialize for crate::Pid {
67    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68    where
69        S: Serializer,
70    {
71        serializer.serialize_newtype_struct("Pid", &self.to_string())
72    }
73}
74
75#[cfg(feature = "system")]
76impl Serialize for crate::Process {
77    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78    where
79        S: Serializer,
80    {
81        // `19` corresponds to the (maximum) number of fields.
82        let mut state = serializer.serialize_struct("Process", 19)?;
83
84        state.serialize_field("name", &self.name().to_string_lossy())?;
85        state.serialize_field("cmd", &self.cmd())?;
86        state.serialize_field("exe", &self.exe())?;
87        state.serialize_field("pid", &self.pid().as_u32())?;
88        state.serialize_field("environ", &self.environ())?;
89        state.serialize_field("cwd", &self.cwd())?;
90        state.serialize_field("root", &self.root())?;
91        state.serialize_field("memory", &self.memory())?;
92        state.serialize_field("virtual_memory", &self.virtual_memory())?;
93        state.serialize_field("parent", &self.parent())?;
94        state.serialize_field("status", &self.status())?;
95        state.serialize_field("start_time", &self.start_time())?;
96        state.serialize_field("run_time", &self.run_time())?;
97        state.serialize_field("cpu_usage", &self.cpu_usage())?;
98        state.serialize_field("accumulated_cpu_time", &self.accumulated_cpu_time())?;
99        state.serialize_field("disk_usage", &self.disk_usage())?;
100        state.serialize_field("user_id", &self.user_id())?;
101        state.serialize_field("group_id", &self.group_id())?;
102        state.serialize_field("session_id", &self.session_id())?;
103
104        state.end()
105    }
106}
107
108#[cfg(feature = "system")]
109impl Serialize for crate::Cpu {
110    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
111    where
112        S: Serializer,
113    {
114        // `5` corresponds to the number of fields.
115        let mut state = serializer.serialize_struct("Cpu", 5)?;
116
117        state.serialize_field("cpu_usage", &self.cpu_usage())?;
118        state.serialize_field("name", &self.name())?;
119        state.serialize_field("vendor_id", &self.vendor_id())?;
120        state.serialize_field("brand", &self.brand())?;
121        state.serialize_field("frequency", &self.frequency())?;
122
123        state.end()
124    }
125}
126
127#[cfg(feature = "system")]
128impl serde::Serialize for crate::System {
129    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
130    where
131        S: serde::Serializer,
132    {
133        // `19` corresponds to the number of fields.
134        let mut state = serializer.serialize_struct("System", 19)?;
135
136        state.serialize_field("global_cpu_usage", &self.global_cpu_usage())?;
137        state.serialize_field("cpus", &self.cpus())?;
138
139        state.serialize_field("physical_core_count", &Self::physical_core_count())?;
140        state.serialize_field("total_memory", &self.total_memory())?;
141        state.serialize_field("free_memory", &self.free_memory())?;
142        state.serialize_field("available_memory", &self.available_memory())?;
143        state.serialize_field("used_memory", &self.used_memory())?;
144        state.serialize_field("total_swap", &self.total_swap())?;
145        state.serialize_field("free_swap", &self.free_swap())?;
146        state.serialize_field("used_swap", &self.used_swap())?;
147
148        state.serialize_field("uptime", &Self::uptime())?;
149        state.serialize_field("boot_time", &Self::boot_time())?;
150        state.serialize_field("load_average", &Self::load_average())?;
151        state.serialize_field("name", &Self::name())?;
152        state.serialize_field("kernel_version", &Self::kernel_version())?;
153        state.serialize_field("os_version", &Self::os_version())?;
154        state.serialize_field("long_os_version", &Self::long_os_version())?;
155        state.serialize_field("distribution_id", &Self::distribution_id())?;
156        state.serialize_field("host_name", &Self::host_name())?;
157
158        state.end()
159    }
160}
161#[cfg(feature = "system")]
162impl serde::Serialize for crate::Motherboard {
163    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
164    where
165        S: serde::Serializer,
166    {
167        // `5` corresponds to the number of fields.
168        let mut state = serializer.serialize_struct("Motherboard", 5)?;
169
170        state.serialize_field("name", &self.name())?;
171        state.serialize_field("vendor_name", &self.vendor_name())?;
172        state.serialize_field("version", &self.version())?;
173        state.serialize_field("serial_number", &self.serial_number())?;
174        state.serialize_field("asset_tag", &self.asset_tag())?;
175
176        state.end()
177    }
178}
179
180#[cfg(feature = "system")]
181impl serde::Serialize for crate::Product {
182    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
183    where
184        S: serde::Serializer,
185    {
186        // `7` corresponds to the number of "fields".
187        let mut state = serializer.serialize_struct("Product", 5)?;
188
189        state.serialize_field("name", &Self::name())?;
190        state.serialize_field("family", &Self::family())?;
191        state.serialize_field("serial_number", &Self::serial_number())?;
192        state.serialize_field("stock_keeping_unit", &Self::stock_keeping_unit())?;
193        state.serialize_field("uuid", &Self::uuid())?;
194        state.serialize_field("version", &Self::version())?;
195        state.serialize_field("vendor_name", &Self::vendor_name())?;
196
197        state.end()
198    }
199}
200
201#[cfg(feature = "system")]
202impl Serialize for crate::CGroupLimits {
203    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
204    where
205        S: Serializer,
206    {
207        // `3` corresponds to the number of fields.
208        let mut state = serializer.serialize_struct("CGroupLimits", 3)?;
209
210        state.serialize_field("total_memory", &self.total_memory)?;
211        state.serialize_field("free_memory", &self.free_memory)?;
212        state.serialize_field("free_swap", &self.free_swap)?;
213
214        state.end()
215    }
216}
217
218#[cfg(feature = "system")]
219impl Serialize for crate::ThreadKind {
220    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
221    where
222        S: Serializer,
223    {
224        let (index, variant) = match *self {
225            Self::Kernel => (0, "Kernel"),
226            Self::Userland => (1, "Userland"),
227        };
228
229        serializer.serialize_unit_variant("ThreadKind", index, variant)
230    }
231}
232
233#[cfg(feature = "system")]
234impl Serialize for crate::Signal {
235    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
236    where
237        S: Serializer,
238    {
239        let (index, variant) = match *self {
240            Self::Hangup => (0, "Hangup"),
241            Self::Interrupt => (1, "Interrupt"),
242            Self::Quit => (2, "Quit"),
243            Self::Illegal => (3, "Illegal"),
244            Self::Trap => (4, "Trap"),
245            Self::Abort => (5, "Abort"),
246            Self::IOT => (6, "IOT"),
247            Self::Bus => (7, "Bus"),
248            Self::FloatingPointException => (8, "FloatingPointException"),
249            Self::Kill => (9, "Kill"),
250            Self::User1 => (10, "User1"),
251            Self::Segv => (11, "Segv"),
252            Self::User2 => (12, "User2"),
253            Self::Pipe => (13, "Pipe"),
254            Self::Alarm => (14, "Alarm"),
255            Self::Term => (15, "Term"),
256            Self::Child => (16, "Child"),
257            Self::Continue => (17, "Continue"),
258            Self::Stop => (18, "Stop"),
259            Self::TSTP => (19, "TSTP"),
260            Self::TTIN => (20, "TTIN"),
261            Self::TTOU => (21, "TTOU"),
262            Self::Urgent => (22, "Urgent"),
263            Self::XCPU => (23, "XCPU"),
264            Self::XFSZ => (24, "XFSZ"),
265            Self::VirtualAlarm => (25, "VirtualAlarm"),
266            Self::Profiling => (26, "Profiling"),
267            Self::Winch => (27, "Winch"),
268            Self::IO => (28, "IO"),
269            Self::Poll => (29, "Poll"),
270            Self::Power => (30, "Power"),
271            Self::Sys => (31, "Sys"),
272        };
273
274        serializer.serialize_unit_variant("Signal", index, variant)
275    }
276}
277
278#[cfg(feature = "system")]
279impl Serialize for crate::LoadAvg {
280    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
281    where
282        S: Serializer,
283    {
284        // `3` corresponds to the number of fields.
285        let mut state = serializer.serialize_struct("LoadAvg", 3)?;
286
287        state.serialize_field("one", &self.one)?;
288        state.serialize_field("five", &self.five)?;
289        state.serialize_field("fifteen", &self.fifteen)?;
290        state.end()
291    }
292}
293
294#[cfg(feature = "system")]
295impl Serialize for crate::ProcessStatus {
296    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
297    where
298        S: Serializer,
299    {
300        let (index, variant, maybe_value) = match *self {
301            Self::Idle => (0, "Idle", None),
302            Self::Run => (1, "Run", None),
303            Self::Sleep => (2, "Sleep", None),
304            Self::Stop => (3, "Stop", None),
305            Self::Zombie => (4, "Zombie", None),
306            Self::Tracing => (5, "Tracing", None),
307            Self::Dead => (6, "Dead", None),
308            Self::Wakekill => (7, "Wakekill", None),
309            Self::Waking => (8, "Waking", None),
310            Self::Parked => (9, "Parked", None),
311            Self::LockBlocked => (10, "LockBlocked", None),
312            Self::UninterruptibleDiskSleep => (11, "UninterruptibleDiskSleep", None),
313            Self::Suspended => (12, "Suspended", None),
314            Self::Unknown(n) => (13, "Unknown", Some(n)),
315        };
316
317        if let Some(ref value) = maybe_value {
318            serializer.serialize_newtype_variant("ProcessStatus", index, variant, value)
319        } else {
320            serializer.serialize_unit_variant("ProcessStatus", index, variant)
321        }
322    }
323}
324
325#[cfg(feature = "system")]
326impl Serialize for crate::DiskUsage {
327    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
328    where
329        S: Serializer,
330    {
331        // `4` corresponds to the number of fields.
332        let mut state = serializer.serialize_struct("DiskUsage", 4)?;
333
334        state.serialize_field("total_written_bytes", &self.total_written_bytes)?;
335        state.serialize_field("written_bytes", &self.written_bytes)?;
336        state.serialize_field("total_read_bytes", &self.total_read_bytes)?;
337        state.serialize_field("read_bytes", &self.read_bytes)?;
338
339        state.end()
340    }
341}
342
343#[cfg(feature = "component")]
344impl Serialize for crate::Components {
345    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
346    where
347        S: Serializer,
348    {
349        serializer.collect_seq(self.iter())
350    }
351}
352
353#[cfg(feature = "component")]
354impl Serialize for crate::Component {
355    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
356    where
357        S: Serializer,
358    {
359        // `4` corresponds to the number of fields.
360        let mut state = serializer.serialize_struct("Component", 4)?;
361
362        state.serialize_field("temperature", &self.temperature())?;
363        state.serialize_field("max", &self.max())?;
364        state.serialize_field("critical", &self.critical())?;
365        state.serialize_field("label", &self.label())?;
366
367        state.end()
368    }
369}
370
371#[cfg(feature = "network")]
372impl Serialize for crate::Networks {
373    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
374    where
375        S: Serializer,
376    {
377        serializer.collect_seq(self.iter())
378    }
379}
380
381#[cfg(feature = "network")]
382impl Serialize for crate::NetworkData {
383    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
384    where
385        S: Serializer,
386    {
387        // `14` corresponds to the number of fields.
388        let mut state = serializer.serialize_struct("NetworkData", 14)?;
389
390        state.serialize_field("received", &self.received())?;
391        state.serialize_field("total_received", &self.total_received())?;
392        state.serialize_field("transmitted", &self.transmitted())?;
393        state.serialize_field("total_transmitted", &self.total_transmitted())?;
394        state.serialize_field("packets_received", &self.packets_received())?;
395        state.serialize_field("total_packets_received", &self.total_packets_received())?;
396        state.serialize_field("packets_transmitted", &self.packets_transmitted())?;
397        state.serialize_field(
398            "total_packets_transmitted",
399            &self.total_packets_transmitted(),
400        )?;
401        state.serialize_field("errors_on_received", &self.errors_on_received())?;
402        state.serialize_field("total_errors_on_received", &self.total_errors_on_received())?;
403        state.serialize_field("errors_on_transmitted", &self.errors_on_transmitted())?;
404        state.serialize_field(
405            "total_errors_on_transmitted",
406            &self.total_errors_on_transmitted(),
407        )?;
408        state.serialize_field("mac_address", &self.mac_address())?;
409        state.serialize_field("ip_networks", &self.ip_networks())?;
410        state.serialize_field("mtu", &self.mtu())?;
411
412        state.end()
413    }
414}
415
416#[cfg(feature = "network")]
417impl Serialize for crate::MacAddr {
418    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
419    where
420        S: Serializer,
421    {
422        serializer.serialize_newtype_struct("MacAddr", &self.to_string())
423    }
424}
425
426#[cfg(feature = "network")]
427impl Serialize for crate::IpNetwork {
428    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
429    where
430        S: Serializer,
431    {
432        let mut state = serializer.serialize_struct("IpNetwork", 2)?;
433
434        state.serialize_field("addr", &self.addr)?;
435        state.serialize_field("prefix", &self.prefix)?;
436
437        state.end()
438    }
439}
440
441#[cfg(feature = "user")]
442impl Serialize for crate::Users {
443    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
444    where
445        S: Serializer,
446    {
447        serializer.collect_seq(self.iter())
448    }
449}
450
451#[cfg(feature = "user")]
452impl Serialize for crate::User {
453    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
454    where
455        S: Serializer,
456    {
457        // `4` corresponds to the number of fields.
458        let mut state = serializer.serialize_struct("User", 4)?;
459
460        state.serialize_field("id", &self.id())?;
461        state.serialize_field("group_id", &self.group_id())?;
462        state.serialize_field("name", &self.name())?;
463        state.serialize_field("groups", &self.groups())?;
464
465        state.end()
466    }
467}
468
469#[cfg(feature = "user")]
470impl Serialize for crate::Group {
471    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
472    where
473        S: Serializer,
474    {
475        // `2` corresponds to the number of fields.
476        let mut state = serializer.serialize_struct("Group", 2)?;
477
478        state.serialize_field("id", &self.id())?;
479        state.serialize_field("name", &self.name())?;
480
481        state.end()
482    }
483}
484
485#[cfg(any(feature = "user", feature = "system"))]
486impl Serialize for crate::Gid {
487    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
488    where
489        S: Serializer,
490    {
491        serializer.serialize_newtype_struct("Gid", &self.to_string())
492    }
493}
494
495#[cfg(any(feature = "user", feature = "system"))]
496impl Serialize for crate::Uid {
497    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
498    where
499        S: Serializer,
500    {
501        serializer.serialize_newtype_struct("Uid", &self.to_string())
502    }
503}
504
505#[cfg(test)]
506mod tests {
507    #[test]
508    fn test_serde_process_name() {
509        if !crate::IS_SUPPORTED_SYSTEM {
510            return;
511        }
512        let mut s = crate::System::new();
513        s.refresh_processes_specifics(
514            crate::ProcessesToUpdate::All,
515            false,
516            crate::ProcessRefreshKind::nothing(),
517        );
518
519        if s.processes().is_empty() {
520            panic!("no processes?");
521        }
522
523        for p in s.processes().values() {
524            let values = match serde_json::to_value(p) {
525                Ok(serde_json::Value::Object(values)) => values,
526                other => panic!("expected object, found `{other:?}`"),
527            };
528            match values.get("name") {
529                Some(serde_json::Value::String(_)) => {}
530                value => panic!("expected a string, found `{value:?}`"),
531            }
532        }
533    }
534
535    #[test]
536    #[cfg(feature = "network")]
537    fn test_serde_mac_address() {
538        let m = crate::MacAddr([0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]);
539
540        let value = match serde_json::to_value(m) {
541            Ok(serde_json::Value::String(value)) => value,
542            other => panic!("expected string, found `{other:?}`"),
543        };
544        assert_eq!(value, "12:34:56:78:9a:bc");
545    }
546
547    #[test]
548    #[cfg(feature = "disk")]
549    fn test_serde_disk_file_system() {
550        let mut disk = crate::Disk {
551            inner: crate::DiskInner::default(),
552        };
553        disk.inner.file_system = "ZFS".into();
554
555        let obj = match serde_json::to_value(disk) {
556            Ok(serde_json::Value::Object(obj)) => obj,
557            other => panic!("expected object, found `{other:?}`"),
558        };
559        assert_eq!(
560            obj.get("file_system"),
561            Some(&serde_json::Value::String("ZFS".to_string()))
562        );
563    }
564}