1use crate::Input;
2use crate::Output;
3
4use alloc::vec::Vec;
5use std::ffi::OsString;
6use std::path::Path;
7use std::path::PathBuf;
8
9pub struct PathBufOutput {
13 #[cfg(windows)]
14 bytes: Vec<u16>,
15 #[cfg(unix)]
16 bytes: Vec<u8>,
17}
18
19impl PathBufOutput {
20 pub fn into_path_buf(self) -> PathBuf {
22 #[cfg(unix)]
23 let buf = OsString::from_vec(self.bytes).into();
24 #[cfg(windows)]
25 let buf = OsString::from_wide(&self.bytes[..]).into();
26 buf
27 }
28
29 pub fn from_path_buf(path: PathBuf) -> Self {
33 #[cfg(unix)]
34 let bytes = path.into_os_string().into_vec();
35 #[cfg(windows)]
36 let bytes = path.as_os_str().encode_wide().collect();
37 Self { bytes }
38 }
39
40 pub fn from_path(path: &Path) -> Self {
44 #[cfg(unix)]
45 let bytes = path.as_os_str().as_bytes().to_vec();
46 #[cfg(windows)]
47 let bytes = path.as_os_str().encode_wide().collect();
48 Self { bytes }
49 }
50
51 pub const fn new() -> Self {
53 Self { bytes: Vec::new() }
54 }
55
56 pub fn with_capacity(capacity: usize) -> Self {
58 Self {
59 bytes: Vec::with_capacity(capacity),
60 }
61 }
62}
63
64impl From<PathBufOutput> for PathBuf {
65 fn from(other: PathBufOutput) -> Self {
66 other.into_path_buf()
67 }
68}
69
70impl From<PathBuf> for PathBufOutput {
71 fn from(other: PathBuf) -> Self {
72 Self::from_path_buf(other)
73 }
74}
75
76impl Output for PathBufOutput {
77 fn push(&mut self, ch: u8) {
78 #[cfg(windows)]
79 let ch = ch.into();
80 self.bytes.push(ch)
81 }
82}
83
84pub struct PathBufInput<'a> {
88 #[cfg(unix)]
89 inner: &'a [u8],
90 #[cfg(windows)]
91 inner: WideCharIter<'a>,
92}
93
94impl<'a> PathBufInput<'a> {
95 pub fn new(path: &'a Path) -> Self {
97 #[cfg(unix)]
98 let inner = path.as_os_str().as_bytes();
99 #[cfg(windows)]
100 let inner = WideCharIter::new(path.as_os_str().encode_wide());
101 Self { inner }
102 }
103}
104
105impl<'a> From<&'a Path> for PathBufInput<'a> {
106 fn from(other: &'a Path) -> Self {
107 Self::new(other)
108 }
109}
110
111impl Input<8> for PathBufInput<'_> {
112 fn next_chunk(&mut self) -> Option<&[u8]> {
113 Input::<8>::next_chunk(&mut self.inner)
114 }
115
116 fn remainder(&self) -> &[u8] {
117 Input::<8>::remainder(&self.inner)
118 }
119}
120
121#[cfg(unix)]
122mod unix {
123 pub use std::os::unix::ffi::OsStrExt;
124 pub use std::os::unix::ffi::OsStringExt;
125}
126
127#[cfg(unix)]
128use self::unix::*;
129
130#[cfg(windows)]
131mod windows {
132 use crate::Input;
133
134 pub use std::os::windows::ffi::EncodeWide;
135 pub use std::os::windows::ffi::OsStrExt;
136 pub use std::os::windows::ffi::OsStringExt;
137
138 pub struct WideCharIter<'a> {
139 iter: EncodeWide<'a>,
140 chunk: [u8; 8],
141 remainder_len: usize,
142 }
143
144 impl<'a> WideCharIter<'a> {
145 pub fn new(iter: EncodeWide<'a>) -> Self {
146 Self {
147 iter,
148 chunk: [0; 8],
149 remainder_len: 0,
150 }
151 }
152 }
153
154 impl<'a> Input<8> for WideCharIter<'a> {
155 fn next_chunk(&mut self) -> Option<&[u8]> {
156 for i in 0..8 {
157 match self.iter.next() {
158 Some(x) => self.chunk[i] = x.try_into().unwrap_or(u8::MAX),
160 None => {
161 self.remainder_len = i;
162 return None;
163 }
164 }
165 }
166 Some(&self.chunk[..])
167 }
168
169 fn remainder(&self) -> &[u8] {
170 &self.chunk[..self.remainder_len]
171 }
172 }
173}
174
175#[cfg(windows)]
176use self::windows::*;