use std::cmp; use std::io; use std::ptr; use winapi::shared::minwindef::*; use winapi::shared::ntdef::{BOOLEAN, FALSE, HANDLE, TRUE}; use winapi::shared::winerror::*; use winapi::um::fileapi::*; use winapi::um::handleapi::*; use winapi::um::ioapiset::*; use winapi::um::minwinbase::*; #[derive(Debug)] pub struct Handle(HANDLE); unsafe impl Send for Handle {} unsafe impl Sync for Handle {} impl Handle { pub fn new(handle: HANDLE) -> Handle { Handle(handle) } pub fn raw(&self) -> HANDLE { self.0 } pub fn into_raw(self) -> HANDLE { use std::mem; let ret = self.0; mem::forget(self); ret } pub fn write(&self, buf: &[u8]) -> io::Result { let mut bytes = 0; let len = cmp::min(buf.len(), ::max_value() as usize) as DWORD; crate::cvt(unsafe { WriteFile( self.0, buf.as_ptr() as *const _, len, &mut bytes, 0 as *mut _, ) })?; Ok(bytes as usize) } pub fn read(&self, buf: &mut [u8]) -> io::Result { let mut bytes = 0; let len = cmp::min(buf.len(), ::max_value() as usize) as DWORD; crate::cvt(unsafe { ReadFile( self.0, buf.as_mut_ptr() as *mut _, len, &mut bytes, 0 as *mut _, ) })?; Ok(bytes as usize) } pub unsafe fn read_overlapped( &self, buf: &mut [u8], overlapped: *mut OVERLAPPED, ) -> io::Result> { self.read_overlapped_helper(buf, overlapped, FALSE) } pub unsafe fn read_overlapped_wait( &self, buf: &mut [u8], overlapped: *mut OVERLAPPED, ) -> io::Result { match self.read_overlapped_helper(buf, overlapped, TRUE) { Ok(Some(bytes)) => Ok(bytes), Ok(None) => panic!("logic error"), Err(e) => Err(e), } } pub unsafe fn read_overlapped_helper( &self, buf: &mut [u8], overlapped: *mut OVERLAPPED, wait: BOOLEAN, ) -> io::Result> { let len = cmp::min(buf.len(), ::max_value() as usize) as DWORD; let res = crate::cvt({ ReadFile( self.0, buf.as_mut_ptr() as *mut _, len, ptr::null_mut(), overlapped, ) }); match res { Ok(_) => (), Err(ref e) if e.raw_os_error() == Some(ERROR_IO_PENDING as i32) => (), Err(e) => return Err(e), } let mut bytes = 0; let res = crate::cvt({ GetOverlappedResult(self.0, overlapped, &mut bytes, wait as BOOL) }); match res { Ok(_) => Ok(Some(bytes as usize)), Err(ref e) if e.raw_os_error() == Some(ERROR_IO_INCOMPLETE as i32) && wait == FALSE => { Ok(None) } Err(e) => Err(e), } } pub unsafe fn write_overlapped( &self, buf: &[u8], overlapped: *mut OVERLAPPED, ) -> io::Result> { self.write_overlapped_helper(buf, overlapped, FALSE) } pub unsafe fn write_overlapped_wait( &self, buf: &[u8], overlapped: *mut OVERLAPPED, ) -> io::Result { match self.write_overlapped_helper(buf, overlapped, TRUE) { Ok(Some(bytes)) => Ok(bytes), Ok(None) => panic!("logic error"), Err(e) => Err(e), } } unsafe fn write_overlapped_helper( &self, buf: &[u8], overlapped: *mut OVERLAPPED, wait: BOOLEAN, ) -> io::Result> { let len = cmp::min(buf.len(), ::max_value() as usize) as DWORD; let res = crate::cvt({ WriteFile( self.0, buf.as_ptr() as *const _, len, ptr::null_mut(), overlapped, ) }); match res { Ok(_) => (), Err(ref e) if e.raw_os_error() == Some(ERROR_IO_PENDING as i32) => (), Err(e) => return Err(e), } let mut bytes = 0; let res = crate::cvt({ GetOverlappedResult(self.0, overlapped, &mut bytes, wait as BOOL) }); match res { Ok(_) => Ok(Some(bytes as usize)), Err(ref e) if e.raw_os_error() == Some(ERROR_IO_INCOMPLETE as i32) && wait == FALSE => { Ok(None) } Err(e) => Err(e), } } } impl Drop for Handle { fn drop(&mut self) { unsafe { CloseHandle(self.0) }; } }