use std::{
fs::File,
io,
os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle},
path::Path,
process,
};
#[derive(Debug)]
pub struct Handle(File);
impl AsRawHandle for Handle {
fn as_raw_handle(&self) -> RawHandle {
self.0.as_raw_handle()
}
}
impl FromRawHandle for Handle {
unsafe fn from_raw_handle(handle: RawHandle) -> Handle {
Handle(File::from_raw_handle(handle))
}
}
impl IntoRawHandle for Handle {
fn into_raw_handle(self) -> RawHandle {
self.0.into_raw_handle()
}
}
impl Handle {
pub fn from_file(file: File) -> Handle {
Handle(file)
}
pub fn from_path<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
Ok(Handle::from_file(File::open(path)?))
}
pub fn from_path_any<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
use std::fs::OpenOptions;
use std::os::windows::fs::OpenOptionsExt;
use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_BACKUP_SEMANTICS;
let file = OpenOptions::new()
.read(true)
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
.open(path)?;
Ok(Handle::from_file(file))
}
pub fn as_file(&self) -> &File {
&self.0
}
pub fn as_file_mut(&mut self) -> &mut File {
&mut self.0
}
}
#[derive(Debug)]
pub struct HandleRef(HandleRefInner);
#[derive(Debug)]
struct HandleRefInner(Option<File>);
impl Drop for HandleRefInner {
fn drop(&mut self) {
self.0.take().unwrap().into_raw_handle();
}
}
impl AsRawHandle for HandleRef {
fn as_raw_handle(&self) -> RawHandle {
self.as_file().as_raw_handle()
}
}
impl Clone for HandleRef {
fn clone(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}
impl HandleRef {
pub fn stdin() -> HandleRef {
unsafe { HandleRef::from_raw_handle(io::stdin().as_raw_handle()) }
}
pub fn stdout() -> HandleRef {
unsafe { HandleRef::from_raw_handle(io::stdout().as_raw_handle()) }
}
pub fn stderr() -> HandleRef {
unsafe { HandleRef::from_raw_handle(io::stderr().as_raw_handle()) }
}
pub fn from_file(file: &File) -> HandleRef {
unsafe { HandleRef::from_raw_handle(file.as_raw_handle()) }
}
pub unsafe fn from_raw_handle(handle: RawHandle) -> HandleRef {
HandleRef(HandleRefInner(Some(File::from_raw_handle(handle))))
}
pub fn as_file(&self) -> &File {
(self.0).0.as_ref().unwrap()
}
pub fn as_file_mut(&mut self) -> &mut File {
(self.0).0.as_mut().unwrap()
}
}
pub trait AsHandleRef {
fn as_handle_ref(&self) -> HandleRef;
fn as_raw(&self) -> RawHandle {
self.as_handle_ref().as_raw_handle()
}
}
impl<'a, T: AsHandleRef> AsHandleRef for &'a T {
fn as_handle_ref(&self) -> HandleRef {
(**self).as_handle_ref()
}
}
impl AsHandleRef for Handle {
fn as_handle_ref(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}
impl AsHandleRef for HandleRef {
fn as_handle_ref(&self) -> HandleRef {
self.clone()
}
}
impl AsHandleRef for File {
fn as_handle_ref(&self) -> HandleRef {
HandleRef::from_file(self)
}
}
impl AsHandleRef for io::Stdin {
fn as_handle_ref(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}
impl AsHandleRef for io::Stdout {
fn as_handle_ref(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}
impl AsHandleRef for io::Stderr {
fn as_handle_ref(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}
impl AsHandleRef for process::ChildStdin {
fn as_handle_ref(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}
impl AsHandleRef for process::ChildStdout {
fn as_handle_ref(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}
impl AsHandleRef for process::ChildStderr {
fn as_handle_ref(&self) -> HandleRef {
unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
}
}