1use std::{
2 fs::File,
3 io,
4 os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle},
5 path::Path,
6 process,
7};
8
9#[derive(Debug)]
15pub struct Handle(File);
16
17impl AsRawHandle for Handle {
18 fn as_raw_handle(&self) -> RawHandle {
19 self.0.as_raw_handle()
20 }
21}
22
23impl FromRawHandle for Handle {
24 unsafe fn from_raw_handle(handle: RawHandle) -> Handle {
25 Handle(File::from_raw_handle(handle))
26 }
27}
28
29impl IntoRawHandle for Handle {
30 fn into_raw_handle(self) -> RawHandle {
31 self.0.into_raw_handle()
32 }
33}
34
35impl Handle {
36 pub fn from_file(file: File) -> Handle {
48 Handle(file)
49 }
50
51 pub fn from_path<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
59 Ok(Handle::from_file(File::open(path)?))
60 }
61
62 pub fn from_path_any<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
67 use std::fs::OpenOptions;
68 use std::os::windows::fs::OpenOptionsExt;
69 use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_BACKUP_SEMANTICS;
70
71 let file = OpenOptions::new()
72 .read(true)
73 .custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
74 .open(path)?;
75 Ok(Handle::from_file(file))
76 }
77
78 pub fn as_file(&self) -> &File {
80 &self.0
81 }
82
83 pub fn as_file_mut(&mut self) -> &mut File {
85 &mut self.0
86 }
87}
88
89#[derive(Debug)]
95pub struct HandleRef(HandleRefInner);
96
97#[derive(Debug)]
100struct HandleRefInner(Option<File>);
101
102impl Drop for HandleRefInner {
103 fn drop(&mut self) {
104 self.0.take().unwrap().into_raw_handle();
105 }
106}
107
108impl AsRawHandle for HandleRef {
109 fn as_raw_handle(&self) -> RawHandle {
110 self.as_file().as_raw_handle()
111 }
112}
113
114impl Clone for HandleRef {
115 fn clone(&self) -> HandleRef {
116 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
117 }
118}
119
120impl HandleRef {
121 pub fn stdin() -> HandleRef {
125 unsafe { HandleRef::from_raw_handle(io::stdin().as_raw_handle()) }
126 }
127
128 pub fn stdout() -> HandleRef {
132 unsafe { HandleRef::from_raw_handle(io::stdout().as_raw_handle()) }
133 }
134
135 pub fn stderr() -> HandleRef {
139 unsafe { HandleRef::from_raw_handle(io::stderr().as_raw_handle()) }
140 }
141
142 pub fn from_file(file: &File) -> HandleRef {
146 unsafe { HandleRef::from_raw_handle(file.as_raw_handle()) }
147 }
148
149 pub unsafe fn from_raw_handle(handle: RawHandle) -> HandleRef {
162 HandleRef(HandleRefInner(Some(File::from_raw_handle(handle))))
163 }
164
165 pub fn as_file(&self) -> &File {
167 (self.0).0.as_ref().unwrap()
168 }
169
170 pub fn as_file_mut(&mut self) -> &mut File {
172 (self.0).0.as_mut().unwrap()
173 }
174}
175
176pub trait AsHandleRef {
178 fn as_handle_ref(&self) -> HandleRef;
180
181 fn as_raw(&self) -> RawHandle {
184 self.as_handle_ref().as_raw_handle()
185 }
186}
187
188impl<'a, T: AsHandleRef> AsHandleRef for &'a T {
189 fn as_handle_ref(&self) -> HandleRef {
190 (**self).as_handle_ref()
191 }
192}
193
194impl AsHandleRef for Handle {
195 fn as_handle_ref(&self) -> HandleRef {
196 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
197 }
198}
199
200impl AsHandleRef for HandleRef {
201 fn as_handle_ref(&self) -> HandleRef {
202 self.clone()
203 }
204}
205
206impl AsHandleRef for File {
207 fn as_handle_ref(&self) -> HandleRef {
208 HandleRef::from_file(self)
209 }
210}
211
212impl AsHandleRef for io::Stdin {
213 fn as_handle_ref(&self) -> HandleRef {
214 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
215 }
216}
217
218impl AsHandleRef for io::Stdout {
219 fn as_handle_ref(&self) -> HandleRef {
220 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
221 }
222}
223
224impl AsHandleRef for io::Stderr {
225 fn as_handle_ref(&self) -> HandleRef {
226 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
227 }
228}
229
230impl AsHandleRef for process::ChildStdin {
231 fn as_handle_ref(&self) -> HandleRef {
232 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
233 }
234}
235
236impl AsHandleRef for process::ChildStdout {
237 fn as_handle_ref(&self) -> HandleRef {
238 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
239 }
240}
241
242impl AsHandleRef for process::ChildStderr {
243 fn as_handle_ref(&self) -> HandleRef {
244 unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
245 }
246}