|
16 | 16 |
|
17 | 17 | //! Cross-platform open url in default browser
|
18 | 18 |
|
| 19 | +use std; |
| 20 | +use std::os::raw::c_int; |
| 21 | + |
| 22 | +#[allow(unused)] |
| 23 | +pub enum Error { |
| 24 | + ProcessError(std::io::Error), |
| 25 | + WindowsShellExecute(c_int), |
| 26 | +} |
| 27 | + |
| 28 | +impl From<std::io::Error> for Error { |
| 29 | + fn from(err: std::io::Error) -> Self { |
| 30 | + Error::ProcessError(err) |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +impl std::fmt::Display for Error { |
| 35 | + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { |
| 36 | + match *self { |
| 37 | + Error::ProcessError(ref e) => write!(f, "{}", e), |
| 38 | + Error::WindowsShellExecute(e) => write!(f, "WindowsShellExecute error: {}", e), |
| 39 | + } |
| 40 | + } |
| 41 | +} |
| 42 | + |
19 | 43 | #[cfg(windows)]
|
20 |
| -pub fn open(url: &str) { |
| 44 | +pub fn open(url: &str) -> Result<(), Error> { |
21 | 45 | use std::ffi::CString;
|
22 | 46 | use std::ptr;
|
23 | 47 | use winapi::um::shellapi::ShellExecuteA;
|
24 | 48 | use winapi::um::winuser::SW_SHOWNORMAL as Normal;
|
25 | 49 |
|
26 |
| - unsafe { |
| 50 | + const WINDOWS_SHELL_EXECUTE_SUCCESS: c_int = 32; |
| 51 | + |
| 52 | + let h_instance = unsafe { |
27 | 53 | ShellExecuteA(ptr::null_mut(),
|
28 | 54 | CString::new("open").unwrap().as_ptr(),
|
29 | 55 | CString::new(url.to_owned().replace("\n", "%0A")).unwrap().as_ptr(),
|
30 | 56 | ptr::null(),
|
31 | 57 | ptr::null(),
|
32 |
| - Normal); |
| 58 | + Normal) as c_int |
| 59 | + }; |
| 60 | + |
| 61 | + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx |
| 62 | + // `ShellExecute` returns a value greater than 32 on success |
| 63 | + if h_instance > WINDOWS_SHELL_EXECUTE_SUCCESS { |
| 64 | + Ok(()) |
| 65 | + } else { |
| 66 | + Err(Error::WindowsShellExecute(h_instance)) |
33 | 67 | }
|
34 | 68 | }
|
35 | 69 |
|
36 | 70 | #[cfg(any(target_os="macos", target_os="freebsd"))]
|
37 |
| -pub fn open(url: &str) { |
38 |
| - use std; |
39 |
| - let _ = std::process::Command::new("open").arg(url).spawn(); |
| 71 | +pub fn open(url: &str) -> Result<(), Error> { |
| 72 | + let _ = std::process::Command::new("open").arg(url).spawn()?; |
| 73 | + Ok(()) |
40 | 74 | }
|
41 | 75 |
|
42 | 76 | #[cfg(target_os="linux")]
|
43 |
| -pub fn open(url: &str) { |
44 |
| - use std; |
45 |
| - let _ = std::process::Command::new("xdg-open").arg(url).spawn(); |
| 77 | +pub fn open(url: &str) -> Result<(), Error> { |
| 78 | + let _ = std::process::Command::new("xdg-open").arg(url).spawn()?; |
| 79 | + Ok(()) |
46 | 80 | }
|
47 | 81 |
|
48 | 82 | #[cfg(target_os="android")]
|
|
0 commit comments