1 | //! Platform dependent types. |
2 | |
3 | cfg_if::cfg_if! { |
4 | if #[cfg(feature = "std" )] { |
5 | use std::borrow::Cow; |
6 | use std::fmt; |
7 | use std::path::PathBuf; |
8 | use std::prelude::v1::*; |
9 | use std::str; |
10 | } |
11 | } |
12 | |
13 | /// A platform independent representation of a string. When working with `std` |
14 | /// enabled it is recommended to the convenience methods for providing |
15 | /// conversions to `std` types. |
16 | #[derive(Debug)] |
17 | pub enum BytesOrWideString<'a> { |
18 | /// A slice, typically provided on Unix platforms. |
19 | Bytes(&'a [u8]), |
20 | /// Wide strings typically from Windows. |
21 | Wide(&'a [u16]), |
22 | } |
23 | |
24 | #[cfg (feature = "std" )] |
25 | impl<'a> BytesOrWideString<'a> { |
26 | /// Lossy converts to a `Cow<str>`, will allocate if `Bytes` is not valid |
27 | /// UTF-8 or if `BytesOrWideString` is `Wide`. |
28 | /// |
29 | /// # Required features |
30 | /// |
31 | /// This function requires the `std` feature of the `backtrace` crate to be |
32 | /// enabled, and the `std` feature is enabled by default. |
33 | pub fn to_str_lossy(&self) -> Cow<'a, str> { |
34 | use self::BytesOrWideString::*; |
35 | |
36 | match self { |
37 | &Bytes(slice) => String::from_utf8_lossy(slice), |
38 | &Wide(wide) => Cow::Owned(String::from_utf16_lossy(wide)), |
39 | } |
40 | } |
41 | |
42 | /// Provides a `Path` representation of `BytesOrWideString`. |
43 | /// |
44 | /// # Required features |
45 | /// |
46 | /// This function requires the `std` feature of the `backtrace` crate to be |
47 | /// enabled, and the `std` feature is enabled by default. |
48 | pub fn into_path_buf(self) -> PathBuf { |
49 | #[cfg (unix)] |
50 | { |
51 | use std::ffi::OsStr; |
52 | use std::os::unix::ffi::OsStrExt; |
53 | |
54 | if let BytesOrWideString::Bytes(slice) = self { |
55 | return PathBuf::from(OsStr::from_bytes(slice)); |
56 | } |
57 | } |
58 | |
59 | #[cfg (windows)] |
60 | { |
61 | use std::ffi::OsString; |
62 | use std::os::windows::ffi::OsStringExt; |
63 | |
64 | if let BytesOrWideString::Wide(slice) = self { |
65 | return PathBuf::from(OsString::from_wide(slice)); |
66 | } |
67 | } |
68 | |
69 | if let BytesOrWideString::Bytes(b) = self { |
70 | if let Ok(s) = str::from_utf8(b) { |
71 | return PathBuf::from(s); |
72 | } |
73 | } |
74 | unreachable!() |
75 | } |
76 | } |
77 | |
78 | #[cfg (feature = "std" )] |
79 | impl<'a> fmt::Display for BytesOrWideString<'a> { |
80 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
81 | self.to_str_lossy().fmt(f) |
82 | } |
83 | } |
84 | |