1use std::{num::ParseIntError, str::FromStr};
2
3use sysinfo::{Pid, Process, SystemExt};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum ProcessQuery {
8 Pid(Pid),
10 Name(String),
12}
13
14impl FromStr for ProcessQuery {
15 type Err = ParseIntError;
16
17 fn from_str(s: &str) -> Result<ProcessQuery, Self::Err> {
18 let value = s.parse::<Pid>().map_or_else(
19 |_| ProcessQuery::Name(s.to_string()),
20 |pid| ProcessQuery::Pid(pid),
21 );
22 Ok(value)
23 }
24}
25
26pub fn search<'a, S: SystemExt>(sys: &'a S, query: &'a ProcessQuery) -> Vec<&'a Process> {
37 match query {
38 ProcessQuery::Pid(pid) => sys
39 .process(*pid)
40 .map_or_else(|| Vec::new(), |process| vec![process]),
41 ProcessQuery::Name(name) => sys.processes_by_name(&name).collect::<Vec<&Process>>(),
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn process_query_should_parse_string() -> anyhow::Result<()> {
51 let result: ProcessQuery = "argument".parse()?;
52
53 assert_eq!(result, ProcessQuery::Name("argument".to_string()));
54
55 Ok(())
56 }
57
58 #[test]
59 fn process_query_should_parse_pid() -> anyhow::Result<()> {
60 let result: ProcessQuery = "1234".parse()?;
61
62 assert_eq!(result, ProcessQuery::Pid(Pid::from(1234)));
63
64 Ok(())
65 }
66}