summaryrefslogtreecommitdiffstats
path: root/src/widgets/process_table/proc_widget_column.rs
blob: e68cad94d445956291c8d1d65f6b36c1d44d74c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
use std::{borrow::Cow, cmp::Reverse};

use serde::{de::Error, Deserialize, Serialize};

use super::ProcWidgetData;
use crate::{
    components::data_table::{ColumnHeader, SortsRow},
    utils::gen_util::sort_partial_fn,
};

#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub enum ProcColumn {
    CpuPercent,
    MemoryVal,
    MemoryPercent,
    Pid,
    Count,
    Name,
    Command,
    ReadPerSecond,
    WritePerSecond,
    TotalRead,
    TotalWrite,
    State,
    User,
    Time,
    #[cfg(feature = "gpu")]
    GpuMem,
    #[cfg(feature = "gpu")]
    GpuMemPercent,
    #[cfg(feature = "gpu")]
    GpuUtilPercent,
}

impl<'de> Deserialize<'de> for ProcColumn {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = String::deserialize(deserializer)?.to_lowercase();
        match value.as_str() {
            "cpu%" => Ok(ProcColumn::CpuPercent),
            "mem" => Ok(ProcColumn::MemoryVal),
            "mem%" => Ok(ProcColumn::MemoryPercent),
            "pid" => Ok(ProcColumn::Pid),
            "count" => Ok(ProcColumn::Count),
            "name" => Ok(ProcColumn::Name),
            "command" => Ok(ProcColumn::Command),
            "read" | "r/s" | "rps" => Ok(ProcColumn::ReadPerSecond),
            "write" | "w/s" | "wps" => Ok(ProcColumn::WritePerSecond),
            "tread" | "t.read" => Ok(ProcColumn::TotalRead),
            "twrite" | "t.write" => Ok(ProcColumn::TotalWrite),
            "state" => Ok(ProcColumn::State),
            "user" => Ok(ProcColumn::User),
            "time" => Ok(ProcColumn::Time),
            #[cfg(feature = "gpu")]
            "gmem" => Ok(ProcColumn::GpuMem),
            #[cfg(feature = "gpu")]
            "gmem%" => Ok(ProcColumn::GpuMemPercent),
            #[cfg(feature = "gpu")]
            "gpu%" => Ok(ProcColumn::GpuUtilPercent),
            _ => Err(Error::custom("doesn't match any column type")),
        }
    }
}

impl Serialize for ProcColumn {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(&self.text())
    }
}

impl ColumnHeader for ProcColumn {
    fn text(&self) -> Cow<'static, str> {
        match self {
            ProcColumn::CpuPercent => "CPU%",
            ProcColumn::MemoryVal => "Mem",
            ProcColumn::MemoryPercent => "Mem%",
            ProcColumn::Pid => "PID",
            ProcColumn::Count => "Count",
            ProcColumn::Name => "Name",
            ProcColumn::Command => "Command",
            ProcColumn::ReadPerSecond => "R/s",
            ProcColumn::WritePerSecond => "W/s",
            ProcColumn::TotalRead => "T.Read",
            ProcColumn::TotalWrite => "T.Write",
            ProcColumn::State => "State",
            ProcColumn::User => "User",
            ProcColumn::Time => "Time",
            #[cfg(feature = "gpu")]
            ProcColumn::GpuMem => "GMem",
            #[cfg(feature = "gpu")]
            ProcColumn::GpuMemPercent => "GMem%",
            #[cfg(feature = "gpu")]
            ProcColumn::GpuUtilPercent => "GPU%",
        }
        .into()
    }

    fn header(&self) -> Cow<'static, str> {
        match self {
            ProcColumn::CpuPercent => "CPU%(c)",
            ProcColumn::MemoryVal => "Mem(m)",
            ProcColumn::MemoryPercent => "Mem%(m)",
            ProcColumn::Pid => "PID(p)",
            ProcColumn::Count => "Count",
            ProcColumn::Name => "Name(n)",
            ProcColumn::Command => "Command(n)",
            ProcColumn::ReadPerSecond => "R/s",
            ProcColumn::WritePerSecond => "W/s",
            ProcColumn::TotalRead => "T.Read",
            ProcColumn::TotalWrite => "T.Write",
            ProcColumn::State => "State",
            ProcColumn::User => "User",
            ProcColumn::Time => "Time",
            #[cfg(feature = "gpu")]
            ProcColumn::GpuMem => "GMem",
            #[cfg(feature = "gpu")]
            ProcColumn::GpuMemPercent => "GMem%",
            #[cfg(feature = "gpu")]
            ProcColumn::GpuUtilPercent => "GPU%",
        }
        .into()
    }
}

impl SortsRow for ProcColumn {
    type DataType = ProcWidgetData;

    fn sort_data(&self, data: &mut [ProcWidgetData], descending: bool) {
        match self {
            ProcColumn::CpuPercent => {
                data.sort_by(|a, b| {
                    sort_partial_fn(descending)(a.cpu_usage_percent, b.cpu_usage_percent)
                });
            }
            ProcColumn::MemoryVal | ProcColumn::MemoryPercent => {
                data.sort_by(|a, b| sort_partial_fn(descending)(&a.mem_usage, &b.mem_usage));
            }
            ProcColumn::Pid => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.pid, b.pid));
            }
            ProcColumn::Count => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.num_similar, b.num_similar));
            }
            ProcColumn::Name | ProcColumn::Command => {
                if descending {
                    data.sort_by_cached_key(|pd| Reverse(pd.id.to_lowercase()));
                } else {
                    data.sort_by_cached_key(|pd| pd.id.to_lowercase());
                }
            }
            ProcColumn::ReadPerSecond => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.rps, b.rps));
            }
            ProcColumn::WritePerSecond => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.wps, b.wps));
            }
            ProcColumn::TotalRead => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.total_read, b.total_read));
            }
            ProcColumn::TotalWrite => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.total_write, b.total_write));
            }
            ProcColumn::State => {
                if descending {
                    data.sort_by_cached_key(|pd| Reverse(pd.process_state.to_lowercase()));
                } else {
                    data.sort_by_cached_key(|pd| pd.process_state.to_lowercase());
                }
            }
            ProcColumn::User => {
                if descending {
                    data.sort_by_cached_key(|pd| Reverse(pd.user.to_lowercase()));
                } else {
                    data.sort_by_cached_key(|pd| pd.user.to_lowercase());
                }
            }
            ProcColumn::Time => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.time, b.time));
            }
            #[cfg(feature = "gpu")]
            ProcColumn::GpuMem | ProcColumn::GpuMemPercent => {
                data.sort_by(|a, b| {
                    sort_partial_fn(descending)(&a.gpu_mem_usage, &b.gpu_mem_usage)
                });
            }
            #[cfg(feature = "gpu")]
            ProcColumn::GpuUtilPercent => {
                data.sort_by(|a, b| sort_partial_fn(descending)(a.gpu_usage, b.gpu_usage));
            }
        }
    }
}