1use std::fmt::Display;
2use std::str::FromStr;
3
4#[cfg(target_os = "windows")]
5use winapi::um::winnt::HANDLE;
6
7#[cfg(not(target_os = "windows"))]
9pub type HANDLE = *mut std::os::raw::c_void;
10
11#[repr(u32)]
12#[derive(PartialEq, Clone, Debug)]
13pub enum Action {
14 Start = 0,
15 Stop = 1,
16 Restart = 2,
17 Query = 3,
18 Close = 4,
19 Subscribe = 5,
20 Update = 6,
21 Kill = 7,
22 Unknown = 8,
23 MessageBox(String),
24 GetHandle(String),
25 CloseHandle(String),
26}
27
28impl Display for Action {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match self {
31 Action::Start => write!(f, "Start"),
32 Action::Stop => write!(f, "Stop"),
33 Action::Restart => write!(f, "Restart"),
34 Action::Query => write!(f, "Query"),
35 Action::Close => write!(f, "Close"),
36 Action::Subscribe => write!(f, "Subscribe"),
37 Action::Update => write!(f, "Update"),
38 Action::Kill => write!(f, "Kill"),
39 Action::Unknown => write!(f, "Unknown"),
40 Action::MessageBox(message) => write!(f, "MessageBox:{}", message),
41 Action::GetHandle(handle) => write!(f, "GetHandle:{}", handle),
42 Action::CloseHandle(handle) => write!(f, "CloseHandle:{}", handle),
43 }
44 }
45}
46
47impl From<&str> for Action {
48 fn from(s: &str) -> Self {
49 match s.trim() {
50 "0" | "Start" => Self::Start,
51 "1" | "Stop" => Self::Stop,
52 "2" | "Restart" => Self::Restart,
53 "3" | "Query" => Self::Query,
54 "4" | "Close" => Self::Close,
55 "5" | "Subscribe" => Self::Subscribe,
56 "6" | "Update" => Self::Update,
57 "7" | "Kill" => Self::Kill,
58 "8" | "Unknown" => Self::Unknown,
59 _ if s.starts_with("MessageBox:") => {
60 let message = s.strip_prefix("MessageBox:").unwrap_or("").trim().to_string();
61 Self::MessageBox(message)
62 },
63 _ if s.starts_with("GetHandle:") => {
64 let handle = s.strip_prefix("GetHandle:").unwrap_or("").trim().to_string();
65 Self::GetHandle(handle)
66 },
67 _ if s.starts_with("CloseHandle:") => {
68 let handle = s.strip_prefix("CloseHandle:").unwrap_or("").trim().to_string();
69 Self::CloseHandle(handle)
70 },
71 _ => Self::Unknown,
72 }
73 }
74}
75
76
77#[derive(PartialEq, Debug, Clone)]
78pub enum DriverStatus {
79 Launched,
80 Running,
81 Stopped,
82 Kill,
83 Warning,
84 Restart,
85 MessageBox(String),
86}
87
88impl FromStr for DriverStatus {
89 type Err = String;
90
91 fn from_str(s: &str) -> Result<Self, Self::Err> {
92 match s {
93 "Launched" => Ok(DriverStatus::Launched),
94 "Running" => Ok(DriverStatus::Running),
95 "Stopped" => Ok(DriverStatus::Stopped),
96 "Warning" => Ok(DriverStatus::Warning),
97 "Kill" => Ok(DriverStatus::Kill),
98 "Restart" => Ok(DriverStatus::Restart),
99 _ => {
100 if s.starts_with("MessageBox:") {
101 let message = s.strip_prefix("MessageBox:").unwrap_or("").trim().to_string();
102 return Ok(DriverStatus::MessageBox(message));
103 }
104 Err(format!("Invalid DriverStatus variant: {}", s))
105 }
106 }
107 }
108}
109
110impl Display for DriverStatus {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 let str = match self {
113 DriverStatus::Launched => "Launched".to_string(),
114 DriverStatus::Kill => "Kill".to_string(),
115 DriverStatus::Running => "Running".to_string(),
116 DriverStatus::Stopped => "Stopped".to_string(),
117 DriverStatus::Warning => "Warning".to_string(),
118 DriverStatus::Restart => "Restart".to_string(),
119 DriverStatus::MessageBox(message) => format!("MessageBox: {}", message),
120 };
121 write!(f, "{}", str)
122 }
123}
124
125
126#[derive(Debug, Clone, Copy)]
127pub struct SafeHandle {
128 pub handle: HANDLE,
129}
130
131unsafe impl Send for SafeHandle {}
132unsafe impl Sync for SafeHandle {}
133
134impl SafeHandle {
135 pub fn new(handle: HANDLE) -> Self {
136 Self { handle }
137 }
138
139 pub fn get_handle(&self) -> HANDLE {
140 self.handle
141 }
142
143 pub fn is_valid(&self) -> bool {
145 #[cfg(target_os = "windows")]
146 {
147 !self.handle.is_null() && self.handle != winapi::um::handleapi::INVALID_HANDLE_VALUE
148 }
149
150 #[cfg(not(target_os = "windows"))]
151 {
152 !self.handle.is_null()
153 }
154 }
155
156 pub fn invalid() -> Self {
158 #[cfg(target_os = "windows")]
159 {
160 Self { handle: winapi::um::handleapi::INVALID_HANDLE_VALUE }
161 }
162
163 #[cfg(not(target_os = "windows"))]
164 {
165 Self { handle: std::ptr::null_mut() }
166 }
167 }
168
169 pub fn null() -> Self {
171 Self { handle: std::ptr::null_mut() }
172 }
173}
174
175#[cfg(target_os = "windows")]
176impl SafeHandle {
177 pub fn from_windows_handle(handle: winapi::um::winnt::HANDLE) -> Self {
179 Self::new(handle)
180 }
181
182 pub fn close(&mut self) -> Result<(), std::io::Error> {
184 if self.is_valid() {
185 unsafe {
186 if winapi::um::handleapi::CloseHandle(self.handle) != 0 {
187 self.handle = winapi::um::handleapi::INVALID_HANDLE_VALUE;
188 Ok(())
189 } else {
190 Err(std::io::Error::last_os_error())
191 }
192 }
193 } else {
194 Ok(()) }
196 }
197}
198
199#[cfg(not(target_os = "windows"))]
200impl SafeHandle {
201 pub fn from_fd(fd: std::os::unix::io::RawFd) -> Self {
203 Self::new(fd as HANDLE)
204 }
205
206 pub fn as_fd(&self) -> std::os::unix::io::RawFd {
208 self.handle as std::os::unix::io::RawFd
209 }
210
211 pub fn close(&mut self) -> Result<(), std::io::Error> {
213 if self.is_valid() {
214 let fd = self.as_fd();
215 unsafe {
216 if libc::close(fd) == 0 {
217 self.handle = std::ptr::null_mut();
218 Ok(())
219 } else {
220 Err(std::io::Error::last_os_error())
221 }
222 }
223 } else {
224 Ok(())
225 }
226 }
227}
228
229impl Default for SafeHandle {
230 fn default() -> Self {
231 Self::null()
232 }
233}
234
235impl PartialEq for SafeHandle {
236 fn eq(&self, other: &Self) -> bool {
237 self.handle == other.handle
238 }
239}
240