sharing/
service.rs

1use std::fmt::Display;
2use std::str::FromStr;
3
4#[cfg(target_os = "windows")]
5use winapi::um::winnt::HANDLE;
6
7// Para macOS y otros Unix, usamos un puntero genérico
8#[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    /// Verifica si el handle es válido (multiplataforma)
144    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    /// Crea un handle inválido (multiplataforma)
157    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    /// Crea un handle nulo (multiplataforma)
170    pub fn null() -> Self {
171        Self { handle: std::ptr::null_mut() }
172    }
173}
174
175#[cfg(target_os = "windows")]
176impl SafeHandle {
177    /// Convierte desde un HANDLE de Windows
178    pub fn from_windows_handle(handle: winapi::um::winnt::HANDLE) -> Self {
179        Self::new(handle)
180    }
181
182    /// Cierra el handle de Windows de manera segura
183    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(()) // Ya está cerrado o es inválido
195        }
196    }
197}
198
199#[cfg(not(target_os = "windows"))]
200impl SafeHandle {
201    /// Convierte desde un file descriptor Unix
202    pub fn from_fd(fd: std::os::unix::io::RawFd) -> Self {
203        Self::new(fd as HANDLE)
204    }
205
206    /// Convierte a file descriptor Unix
207    pub fn as_fd(&self) -> std::os::unix::io::RawFd {
208        self.handle as std::os::unix::io::RawFd
209    }
210
211    /// Cierra el handle Unix de manera segura
212    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