1 use std::fmt; 2 use std::marker::PhantomData; 3 use std::mem::forget; 4 #[cfg(unix)] 5 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 6 #[cfg(target_os = "wasi")] 7 use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 8 #[cfg(windows)] 9 use std::{ 10 convert::TryFrom, 11 os::windows::io::{ 12 AsRawHandle, AsRawSocket, FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket, 13 RawHandle, RawSocket, 14 }, 15 }; 16 #[cfg(all(windows, feature = "close"))] 17 use { 18 windows_sys::Win32::Foundation::{ 19 CloseHandle, DuplicateHandle, SetHandleInformation, BOOL, DUPLICATE_HANDLE_OPTIONS, 20 DUPLICATE_SAME_ACCESS, HANDLE, HANDLE_FLAG_INHERIT, INVALID_HANDLE_VALUE, 21 }, 22 windows_sys::Win32::Networking::WinSock::{ 23 closesocket, WSADuplicateSocketW, WSAGetLastError, WSASocketW, INVALID_SOCKET, SOCKET, 24 SOCKET_ERROR, WSAEINVAL, WSAEPROTOTYPE, WSAPROTOCOL_INFOW, WSA_FLAG_NO_HANDLE_INHERIT, 25 WSA_FLAG_OVERLAPPED, 26 }, 27 windows_sys::Win32::System::Threading::{GetCurrentProcess, GetCurrentProcessId}, 28 }; 29 30 #[cfg(all(windows, not(feature = "close")))] 31 type HANDLE = isize; 32 #[cfg(all(windows, not(feature = "close")))] 33 const INVALID_HANDLE_VALUE: HANDLE = !0 as _; 34 #[cfg(all(windows, not(feature = "close")))] 35 const INVALID_SOCKET: usize = !0 as _; 36 37 /// A borrowed file descriptor. 38 /// 39 /// This has a lifetime parameter to tie it to the lifetime of something that 40 /// owns the file descriptor. 41 /// 42 /// This uses `repr(transparent)` and has the representation of a host file 43 /// descriptor, so it can be used in FFI in places where a file descriptor is 44 /// passed as an argument, it is not captured or consumed, and it never has the 45 /// value `-1`. 46 /// 47 /// This type's `.to_owned()` implementation returns another `BorrowedFd` 48 /// rather than an `OwnedFd`. It just makes a trivial copy of the raw file 49 /// descriptor, which is then borrowed under the same lifetime. 50 #[cfg(any(unix, target_os = "wasi"))] 51 #[derive(Copy, Clone)] 52 #[repr(transparent)] 53 pub struct BorrowedFd<'fd> { 54 fd: RawFd, 55 _phantom: PhantomData<&'fd OwnedFd>, 56 } 57 58 /// A borrowed handle. 59 /// 60 /// This has a lifetime parameter to tie it to the lifetime of something that 61 /// owns the handle. 62 /// 63 /// This uses `repr(transparent)` and has the representation of a host handle, 64 /// so it can be used in FFI in places where a handle is passed as an argument, 65 /// it is not captured or consumed, and it is never null. 66 /// 67 /// Note that it *may* have the value `-1`, which in `BorrowedHandle` always 68 /// represents a valid handle value, such as [the current process handle], and 69 /// not `INVALID_HANDLE_VALUE`, despite the two having the same value. See 70 /// [here] for the full story. 71 /// 72 /// This type's `.to_owned()` implementation returns another `BorrowedHandle` 73 /// rather than an `OwnedHandle`. It just makes a trivial copy of the raw 74 /// handle, which is then borrowed under the same lifetime. 75 /// 76 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 77 /// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks 78 #[cfg(windows)] 79 #[derive(Copy, Clone)] 80 #[repr(transparent)] 81 pub struct BorrowedHandle<'handle> { 82 handle: RawHandle, 83 _phantom: PhantomData<&'handle OwnedHandle>, 84 } 85 86 /// A borrowed socket. 87 /// 88 /// This has a lifetime parameter to tie it to the lifetime of something that 89 /// owns the socket. 90 /// 91 /// This uses `repr(transparent)` and has the representation of a host socket, 92 /// so it can be used in FFI in places where a socket is passed as an argument, 93 /// it is not captured or consumed, and it never has the value 94 /// [`INVALID_SOCKET`]. 95 /// 96 /// This type's `.to_owned()` implementation returns another `BorrowedSocket` 97 /// rather than an `OwnedSocket`. It just makes a trivial copy of the raw 98 /// socket, which is then borrowed under the same lifetime. 99 #[cfg(windows)] 100 #[derive(Copy, Clone)] 101 #[repr(transparent)] 102 pub struct BorrowedSocket<'socket> { 103 socket: RawSocket, 104 _phantom: PhantomData<&'socket OwnedSocket>, 105 } 106 107 /// An owned file descriptor. 108 /// 109 /// This closes the file descriptor on drop. 110 /// 111 /// This uses `repr(transparent)` and has the representation of a host file 112 /// descriptor, so it can be used in FFI in places where a file descriptor is 113 /// passed as a consumed argument or returned as an owned value, and it never 114 /// has the value `-1`. 115 #[cfg(any(unix, target_os = "wasi"))] 116 #[repr(transparent)] 117 pub struct OwnedFd { 118 fd: RawFd, 119 } 120 121 #[cfg(any(unix, target_os = "wasi"))] 122 impl OwnedFd { 123 /// Creates a new `OwnedFd` instance that shares the same underlying file 124 /// description as the existing `OwnedFd` instance. try_clone(&self) -> std::io::Result<Self>125 pub fn try_clone(&self) -> std::io::Result<Self> { 126 crate::AsFd::as_fd(self).try_clone_to_owned() 127 } 128 } 129 130 #[cfg(any(unix, target_os = "wasi"))] 131 impl BorrowedFd<'_> { 132 /// Creates a new `OwnedFd` instance that shares the same underlying file 133 /// description as the existing `BorrowedFd` instance. try_clone_to_owned(&self) -> std::io::Result<OwnedFd>134 pub fn try_clone_to_owned(&self) -> std::io::Result<OwnedFd> { 135 #[cfg(feature = "close")] 136 { 137 #[cfg(unix)] 138 { 139 // We want to atomically duplicate this file descriptor and set the 140 // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This 141 // is a POSIX flag that was added to Linux in 2.6.24. 142 #[cfg(not(target_os = "espidf"))] 143 let cmd = libc::F_DUPFD_CLOEXEC; 144 145 // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics 146 // will never be supported, as this is a bare metal framework with 147 // no capabilities for multi-process execution. While F_DUPFD is also 148 // not supported yet, it might be (currently it returns ENOSYS). 149 #[cfg(target_os = "espidf")] 150 let cmd = libc::F_DUPFD; 151 152 let fd = match unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) } { 153 -1 => return Err(std::io::Error::last_os_error()), 154 fd => fd, 155 }; 156 157 Ok(unsafe { OwnedFd::from_raw_fd(fd) }) 158 } 159 160 #[cfg(target_os = "wasi")] 161 { 162 unreachable!("try_clone is not yet suppported on wasi"); 163 } 164 } 165 166 // If the `close` feature is disabled, we expect users to avoid cloning 167 // `OwnedFd` instances, so that we don't have to call `fcntl`. 168 #[cfg(not(feature = "close"))] 169 { 170 unreachable!("try_clone called without the \"close\" feature in io-lifetimes"); 171 } 172 } 173 } 174 175 /// An owned handle. 176 /// 177 /// This closes the handle on drop. 178 /// 179 /// Note that it *may* have the value `-1`, which in `OwnedHandle` always 180 /// represents a valid handle value, such as [the current process handle], and 181 /// not `INVALID_HANDLE_VALUE`, despite the two having the same value. See 182 /// [here] for the full story. 183 /// 184 /// And, it *may* have the value `NULL` (0), which can occur when consoles are 185 /// detached from processes, or when `windows_subsystem` is used. 186 /// 187 /// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such, 188 /// it must not be used with handles to open registry keys which need to be 189 /// closed with [`RegCloseKey`] instead. 190 /// 191 /// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle 192 /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey 193 /// 194 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 195 /// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks 196 #[cfg(windows)] 197 #[repr(transparent)] 198 pub struct OwnedHandle { 199 handle: RawHandle, 200 } 201 202 #[cfg(windows)] 203 impl OwnedHandle { 204 /// Creates a new `OwnedHandle` instance that shares the same underlying 205 /// object as the existing `OwnedHandle` instance. try_clone(&self) -> std::io::Result<Self>206 pub fn try_clone(&self) -> std::io::Result<Self> { 207 crate::AsHandle::as_handle(self).try_clone_to_owned() 208 } 209 } 210 211 #[cfg(windows)] 212 impl BorrowedHandle<'_> { 213 /// Creates a new `OwnedHandle` instance that shares the same underlying 214 /// object as the existing `BorrowedHandle` instance. try_clone_to_owned(&self) -> std::io::Result<OwnedHandle>215 pub fn try_clone_to_owned(&self) -> std::io::Result<OwnedHandle> { 216 #[cfg(feature = "close")] 217 { 218 self.duplicate(0, false, DUPLICATE_SAME_ACCESS) 219 } 220 221 // If the `close` feature is disabled, we expect users to avoid cloning 222 // `OwnedHandle` instances, so that we don't have to call `fcntl`. 223 #[cfg(not(feature = "close"))] 224 { 225 unreachable!("try_clone called without the \"close\" feature in io-lifetimes"); 226 } 227 } 228 229 #[cfg(feature = "close")] duplicate( &self, access: u32, inherit: bool, options: DUPLICATE_HANDLE_OPTIONS, ) -> std::io::Result<OwnedHandle>230 pub(crate) fn duplicate( 231 &self, 232 access: u32, 233 inherit: bool, 234 options: DUPLICATE_HANDLE_OPTIONS, 235 ) -> std::io::Result<OwnedHandle> { 236 let mut ret = 0 as HANDLE; 237 match unsafe { 238 let cur_proc = GetCurrentProcess(); 239 DuplicateHandle( 240 cur_proc, 241 self.as_raw_handle() as HANDLE, 242 cur_proc, 243 &mut ret, 244 access, 245 inherit as BOOL, 246 options, 247 ) 248 } { 249 0 => return Err(std::io::Error::last_os_error()), 250 _ => (), 251 } 252 unsafe { Ok(OwnedHandle::from_raw_handle(ret as RawHandle)) } 253 } 254 } 255 256 /// An owned socket. 257 /// 258 /// This closes the socket on drop. 259 /// 260 /// This uses `repr(transparent)` and has the representation of a host socket, 261 /// so it can be used in FFI in places where a socket is passed as a consumed 262 /// argument or returned as an owned value, and it never has the value 263 /// [`INVALID_SOCKET`]. 264 #[cfg(windows)] 265 #[repr(transparent)] 266 pub struct OwnedSocket { 267 socket: RawSocket, 268 } 269 270 #[cfg(windows)] 271 impl OwnedSocket { 272 /// Creates a new `OwnedSocket` instance that shares the same underlying 273 /// object as the existing `OwnedSocket` instance. try_clone(&self) -> std::io::Result<Self>274 pub fn try_clone(&self) -> std::io::Result<Self> { 275 crate::AsSocket::as_socket(self).try_clone_to_owned() 276 } 277 278 #[cfg(feature = "close")] 279 #[cfg(not(target_vendor = "uwp"))] set_no_inherit(&self) -> std::io::Result<()>280 fn set_no_inherit(&self) -> std::io::Result<()> { 281 match unsafe { 282 SetHandleInformation(self.as_raw_socket() as HANDLE, HANDLE_FLAG_INHERIT, 0) 283 } { 284 0 => return Err(std::io::Error::last_os_error()), 285 _ => Ok(()), 286 } 287 } 288 289 #[cfg(feature = "close")] 290 #[cfg(target_vendor = "uwp")] set_no_inherit(&self) -> std::io::Result<()>291 fn set_no_inherit(&self) -> std::io::Result<()> { 292 Err(io::Error::new_const( 293 std::io::ErrorKind::Unsupported, 294 &"Unavailable on UWP", 295 )) 296 } 297 } 298 299 #[cfg(windows)] 300 impl BorrowedSocket<'_> { 301 /// Creates a new `OwnedSocket` instance that shares the same underlying 302 /// object as the existing `BorrowedSocket` instance. try_clone_to_owned(&self) -> std::io::Result<OwnedSocket>303 pub fn try_clone_to_owned(&self) -> std::io::Result<OwnedSocket> { 304 #[cfg(feature = "close")] 305 { 306 let mut info = unsafe { std::mem::zeroed::<WSAPROTOCOL_INFOW>() }; 307 let result = unsafe { 308 WSADuplicateSocketW(self.as_raw_socket() as _, GetCurrentProcessId(), &mut info) 309 }; 310 match result { 311 SOCKET_ERROR => return Err(std::io::Error::last_os_error()), 312 0 => (), 313 _ => panic!(), 314 } 315 let socket = unsafe { 316 WSASocketW( 317 info.iAddressFamily, 318 info.iSocketType, 319 info.iProtocol, 320 &mut info, 321 0, 322 WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT, 323 ) 324 }; 325 326 if socket != INVALID_SOCKET { 327 unsafe { Ok(OwnedSocket::from_raw_socket(socket as _)) } 328 } else { 329 let error = unsafe { WSAGetLastError() }; 330 331 if error != WSAEPROTOTYPE && error != WSAEINVAL { 332 return Err(std::io::Error::from_raw_os_error(error)); 333 } 334 335 let socket = unsafe { 336 WSASocketW( 337 info.iAddressFamily, 338 info.iSocketType, 339 info.iProtocol, 340 &mut info, 341 0, 342 WSA_FLAG_OVERLAPPED, 343 ) 344 }; 345 346 if socket == INVALID_SOCKET { 347 return Err(std::io::Error::last_os_error()); 348 } 349 350 unsafe { 351 let socket = OwnedSocket::from_raw_socket(socket as _); 352 socket.set_no_inherit()?; 353 Ok(socket) 354 } 355 } 356 } 357 358 // If the `close` feature is disabled, we expect users to avoid cloning 359 // `OwnedSocket` instances, so that we don't have to call `fcntl`. 360 #[cfg(not(feature = "close"))] 361 { 362 unreachable!("try_clone called without the \"close\" feature in io-lifetimes"); 363 } 364 } 365 } 366 367 /// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used 368 /// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses 369 /// `repr(transparent)` and has the representation of a host handle, so that it can be used in such 370 /// FFI declarations. 371 /// 372 /// The only thing you can usefully do with a `HandleOrInvalid` is to convert it into an 373 /// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for 374 /// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without 375 /// checking for `INVALID_HANDLE_VALUE` first. 376 /// 377 /// This type may hold any handle value that [`OwnedHandle`] may hold, except that when it holds 378 /// `-1`, that value is interpreted to mean `INVALID_HANDLE_VALUE`. 379 /// 380 /// If holds a handle other than `INVALID_HANDLE_VALUE`, it will close the handle on drop. 381 #[cfg(windows)] 382 #[repr(transparent)] 383 #[derive(Debug)] 384 pub struct HandleOrInvalid(RawHandle); 385 386 /// FFI type for handles in return values or out parameters, where `NULL` is used 387 /// as a sentry value to indicate errors, such as in the return value of `CreateThread`. This uses 388 /// `repr(transparent)` and has the representation of a host handle, so that it can be used in such 389 /// FFI declarations. 390 /// 391 /// The only thing you can usefully do with a `HandleOrNull` is to convert it into an 392 /// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for 393 /// `NULL`. This ensures that such FFI calls cannot start using the handle without 394 /// checking for `NULL` first. 395 /// 396 /// This type may hold any handle value that [`OwnedHandle`] may hold. As with `OwnedHandle`, when 397 /// it holds `-1`, that value is interpreted as a valid handle value, such as 398 /// [the current process handle], and not `INVALID_HANDLE_VALUE`. 399 /// 400 /// If this holds a non-null handle, it will close the handle on drop. 401 /// 402 /// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks 403 #[cfg(windows)] 404 #[repr(transparent)] 405 #[derive(Debug)] 406 pub struct HandleOrNull(RawHandle); 407 408 // The Windows [`HANDLE`] type may be transferred across and shared between 409 // thread boundaries (despite containing a `*mut void`, which in general isn't 410 // `Send` or `Sync`). 411 // 412 // [`HANDLE`]: std::os::windows::raw::HANDLE 413 #[cfg(windows)] 414 unsafe impl Send for OwnedHandle {} 415 #[cfg(windows)] 416 unsafe impl Send for HandleOrInvalid {} 417 #[cfg(windows)] 418 unsafe impl Send for HandleOrNull {} 419 #[cfg(windows)] 420 unsafe impl Send for BorrowedHandle<'_> {} 421 #[cfg(windows)] 422 unsafe impl Sync for OwnedHandle {} 423 #[cfg(windows)] 424 unsafe impl Sync for HandleOrInvalid {} 425 #[cfg(windows)] 426 unsafe impl Sync for HandleOrNull {} 427 #[cfg(windows)] 428 unsafe impl Sync for BorrowedHandle<'_> {} 429 430 #[cfg(any(unix, target_os = "wasi"))] 431 impl BorrowedFd<'_> { 432 /// Return a `BorrowedFd` holding the given raw file descriptor. 433 /// 434 /// # Safety 435 /// 436 /// The resource pointed to by `raw` must remain open for the duration of 437 /// the returned `BorrowedFd`, and it must not have the value `-1`. 438 #[inline] borrow_raw(fd: RawFd) -> Self439 pub const unsafe fn borrow_raw(fd: RawFd) -> Self { 440 #[cfg(panic_in_const_fn)] 441 debug_assert!(fd != -1_i32 as RawFd); 442 443 Self { 444 fd, 445 _phantom: PhantomData, 446 } 447 } 448 } 449 450 #[cfg(windows)] 451 impl BorrowedHandle<'_> { 452 /// Return a `BorrowedHandle` holding the given raw handle. 453 /// 454 /// # Safety 455 /// 456 /// The resource pointed to by `handle` must be a valid open handle, it 457 /// must remain open for the duration of the returned `BorrowedHandle`. 458 /// 459 /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is 460 /// sometimes a valid handle value. See [here] for the full story. 461 /// 462 /// And, it *may* have the value `NULL` (0), which can occur when consoles are 463 /// detached from processes, or when `windows_subsystem` is used. 464 /// 465 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 466 #[inline] borrow_raw(handle: RawHandle) -> Self467 pub const unsafe fn borrow_raw(handle: RawHandle) -> Self { 468 Self { 469 handle, 470 _phantom: PhantomData, 471 } 472 } 473 } 474 475 #[cfg(windows)] 476 impl BorrowedSocket<'_> { 477 /// Return a `BorrowedSocket` holding the given raw socket. 478 /// 479 /// # Safety 480 /// 481 /// The resource pointed to by `raw` must remain open for the duration of 482 /// the returned `BorrowedSocket`, and it must not have the value 483 /// [`INVALID_SOCKET`]. 484 #[inline] borrow_raw(socket: RawSocket) -> Self485 pub const unsafe fn borrow_raw(socket: RawSocket) -> Self { 486 #[cfg(panic_in_const_fn)] 487 debug_assert!(socket != INVALID_SOCKET as RawSocket); 488 Self { 489 socket, 490 _phantom: PhantomData, 491 } 492 } 493 } 494 495 #[cfg(windows)] 496 impl TryFrom<HandleOrInvalid> for OwnedHandle { 497 type Error = InvalidHandleError; 498 499 #[inline] try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError>500 fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> { 501 let raw = handle_or_invalid.0; 502 if raw as HANDLE == INVALID_HANDLE_VALUE { 503 // Don't call `CloseHandle`; it'd be harmless, except that it could 504 // overwrite the `GetLastError` error. 505 forget(handle_or_invalid); 506 507 Err(InvalidHandleError(())) 508 } else { 509 Ok(OwnedHandle { handle: raw }) 510 } 511 } 512 } 513 514 #[cfg(windows)] 515 impl TryFrom<HandleOrNull> for OwnedHandle { 516 type Error = NullHandleError; 517 518 #[inline] try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError>519 fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> { 520 let raw = handle_or_null.0; 521 if raw.is_null() { 522 // Don't call `CloseHandle`; it'd be harmless, except that it could 523 // overwrite the `GetLastError` error. 524 forget(handle_or_null); 525 526 Err(NullHandleError(())) 527 } else { 528 Ok(OwnedHandle { handle: raw }) 529 } 530 } 531 } 532 533 /// This is the error type used by [`HandleOrNull`] when attempting to convert 534 /// into a handle, to indicate that the value is null. 535 #[derive(Debug, Clone, PartialEq, Eq)] 536 pub struct NullHandleError(()); 537 538 impl fmt::Display for NullHandleError { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result539 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 540 "A HandleOrNull could not be converted to a handle because it was null".fmt(fmt) 541 } 542 } 543 544 impl std::error::Error for NullHandleError {} 545 546 /// This is the error type used by [`HandleOrInvalid`] when attempting to 547 /// convert into a handle, to indicate that the value is 548 /// `INVALID_HANDLE_VALUE`. 549 #[derive(Debug, Clone, PartialEq, Eq)] 550 pub struct InvalidHandleError(()); 551 552 impl fmt::Display for InvalidHandleError { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result553 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 554 "A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE" 555 .fmt(fmt) 556 } 557 } 558 559 impl std::error::Error for InvalidHandleError {} 560 561 #[cfg(any(unix, target_os = "wasi"))] 562 impl AsRawFd for BorrowedFd<'_> { 563 #[inline] as_raw_fd(&self) -> RawFd564 fn as_raw_fd(&self) -> RawFd { 565 self.fd 566 } 567 } 568 569 #[cfg(windows)] 570 impl AsRawHandle for BorrowedHandle<'_> { 571 #[inline] as_raw_handle(&self) -> RawHandle572 fn as_raw_handle(&self) -> RawHandle { 573 self.handle 574 } 575 } 576 577 #[cfg(windows)] 578 impl AsRawSocket for BorrowedSocket<'_> { 579 #[inline] as_raw_socket(&self) -> RawSocket580 fn as_raw_socket(&self) -> RawSocket { 581 self.socket 582 } 583 } 584 585 #[cfg(any(unix, target_os = "wasi"))] 586 impl AsRawFd for OwnedFd { 587 #[inline] as_raw_fd(&self) -> RawFd588 fn as_raw_fd(&self) -> RawFd { 589 self.fd 590 } 591 } 592 593 #[cfg(windows)] 594 impl AsRawHandle for OwnedHandle { 595 #[inline] as_raw_handle(&self) -> RawHandle596 fn as_raw_handle(&self) -> RawHandle { 597 self.handle 598 } 599 } 600 601 #[cfg(windows)] 602 impl AsRawSocket for OwnedSocket { 603 #[inline] as_raw_socket(&self) -> RawSocket604 fn as_raw_socket(&self) -> RawSocket { 605 self.socket 606 } 607 } 608 609 #[cfg(any(unix, target_os = "wasi"))] 610 impl IntoRawFd for OwnedFd { 611 #[inline] into_raw_fd(self) -> RawFd612 fn into_raw_fd(self) -> RawFd { 613 let fd = self.fd; 614 forget(self); 615 fd 616 } 617 } 618 619 #[cfg(windows)] 620 impl IntoRawHandle for OwnedHandle { 621 #[inline] into_raw_handle(self) -> RawHandle622 fn into_raw_handle(self) -> RawHandle { 623 let handle = self.handle; 624 forget(self); 625 handle 626 } 627 } 628 629 #[cfg(windows)] 630 impl IntoRawSocket for OwnedSocket { 631 #[inline] into_raw_socket(self) -> RawSocket632 fn into_raw_socket(self) -> RawSocket { 633 let socket = self.socket; 634 forget(self); 635 socket 636 } 637 } 638 639 #[cfg(any(unix, target_os = "wasi"))] 640 impl FromRawFd for OwnedFd { 641 /// Constructs a new instance of `Self` from the given raw file descriptor. 642 /// 643 /// # Safety 644 /// 645 /// The resource pointed to by `raw` must be open and suitable for assuming 646 /// ownership. 647 #[inline] from_raw_fd(fd: RawFd) -> Self648 unsafe fn from_raw_fd(fd: RawFd) -> Self { 649 debug_assert_ne!(fd, -1_i32 as RawFd); 650 Self { fd } 651 } 652 } 653 654 #[cfg(windows)] 655 impl FromRawHandle for OwnedHandle { 656 #[inline] from_raw_handle(handle: RawHandle) -> Self657 unsafe fn from_raw_handle(handle: RawHandle) -> Self { 658 Self { handle } 659 } 660 } 661 662 #[cfg(windows)] 663 impl FromRawSocket for OwnedSocket { 664 #[inline] from_raw_socket(socket: RawSocket) -> Self665 unsafe fn from_raw_socket(socket: RawSocket) -> Self { 666 debug_assert_ne!(socket, INVALID_SOCKET as RawSocket); 667 Self { socket } 668 } 669 } 670 671 #[cfg(windows)] 672 impl HandleOrInvalid { 673 /// Constructs a new instance of `Self` from the given `RawHandle` returned 674 /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate 675 /// failure, such as `CreateFileW`. 676 /// 677 /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that 678 /// use null to indicate failure. 679 /// 680 /// # Safety 681 /// 682 /// The passed `handle` value must either satisfy the safety requirements 683 /// of [`FromRawHandle::from_raw_handle`], or be 684 /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use 685 /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story. 686 /// 687 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 688 #[inline] from_raw_handle(handle: RawHandle) -> Self689 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self { 690 Self(handle) 691 } 692 } 693 694 #[cfg(windows)] 695 impl HandleOrNull { 696 /// Constructs a new instance of `Self` from the given `RawHandle` returned 697 /// from a Windows API that uses null to indicate failure, such as 698 /// `CreateThread`. 699 /// 700 /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that 701 /// use `INVALID_HANDLE_VALUE` to indicate failure. 702 /// 703 /// # Safety 704 /// 705 /// The passed `handle` value must either satisfy the safety requirements 706 /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all 707 /// Windows APIs use null for errors; see [here] for the full story. 708 /// 709 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 710 #[inline] from_raw_handle(handle: RawHandle) -> Self711 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self { 712 Self(handle) 713 } 714 } 715 716 #[cfg(any(unix, target_os = "wasi"))] 717 impl Drop for OwnedFd { 718 #[inline] drop(&mut self)719 fn drop(&mut self) { 720 #[cfg(feature = "close")] 721 unsafe { 722 let _ = libc::close(self.fd as std::os::raw::c_int); 723 } 724 725 // If the `close` feature is disabled, we expect users to avoid letting 726 // `OwnedFd` instances drop, so that we don't have to call `close`. 727 #[cfg(not(feature = "close"))] 728 { 729 unreachable!("drop called without the \"close\" feature in io-lifetimes"); 730 } 731 } 732 } 733 734 #[cfg(windows)] 735 impl Drop for OwnedHandle { 736 #[inline] drop(&mut self)737 fn drop(&mut self) { 738 #[cfg(feature = "close")] 739 unsafe { 740 let _ = CloseHandle(self.handle as HANDLE); 741 } 742 743 // If the `close` feature is disabled, we expect users to avoid letting 744 // `OwnedHandle` instances drop, so that we don't have to call `close`. 745 #[cfg(not(feature = "close"))] 746 { 747 unreachable!("drop called without the \"close\" feature in io-lifetimes"); 748 } 749 } 750 } 751 752 #[cfg(windows)] 753 impl Drop for HandleOrInvalid { 754 #[inline] drop(&mut self)755 fn drop(&mut self) { 756 #[cfg(feature = "close")] 757 unsafe { 758 let _ = CloseHandle(self.0 as HANDLE); 759 } 760 761 // If the `close` feature is disabled, we expect users to avoid letting 762 // `HandleOrInvalid` instances drop, so that we don't have to call `close`. 763 #[cfg(not(feature = "close"))] 764 { 765 unreachable!("drop called without the \"close\" feature in io-lifetimes"); 766 } 767 } 768 } 769 770 #[cfg(windows)] 771 impl Drop for HandleOrNull { 772 #[inline] drop(&mut self)773 fn drop(&mut self) { 774 #[cfg(feature = "close")] 775 unsafe { 776 let _ = CloseHandle(self.0 as HANDLE); 777 } 778 779 // If the `close` feature is disabled, we expect users to avoid letting 780 // `HandleOrNull` instances drop, so that we don't have to call `close`. 781 #[cfg(not(feature = "close"))] 782 { 783 unreachable!("drop called without the \"close\" feature in io-lifetimes"); 784 } 785 } 786 } 787 788 #[cfg(windows)] 789 impl Drop for OwnedSocket { 790 #[inline] drop(&mut self)791 fn drop(&mut self) { 792 #[cfg(feature = "close")] 793 unsafe { 794 let _ = closesocket(self.socket as SOCKET); 795 } 796 797 // If the `close` feature is disabled, we expect users to avoid letting 798 // `OwnedSocket` instances drop, so that we don't have to call `close`. 799 #[cfg(not(feature = "close"))] 800 { 801 unreachable!("drop called without the \"close\" feature in io-lifetimes"); 802 } 803 } 804 } 805 806 #[cfg(any(unix, target_os = "wasi"))] 807 impl fmt::Debug for BorrowedFd<'_> { 808 #[allow(clippy::missing_inline_in_public_items)] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result809 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 810 f.debug_struct("BorrowedFd").field("fd", &self.fd).finish() 811 } 812 } 813 814 #[cfg(windows)] 815 impl fmt::Debug for BorrowedHandle<'_> { 816 #[allow(clippy::missing_inline_in_public_items)] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result817 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 818 f.debug_struct("BorrowedHandle") 819 .field("handle", &self.handle) 820 .finish() 821 } 822 } 823 824 #[cfg(windows)] 825 impl fmt::Debug for BorrowedSocket<'_> { 826 #[allow(clippy::missing_inline_in_public_items)] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result827 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 828 f.debug_struct("BorrowedSocket") 829 .field("socket", &self.socket) 830 .finish() 831 } 832 } 833 834 #[cfg(any(unix, target_os = "wasi"))] 835 impl fmt::Debug for OwnedFd { 836 #[allow(clippy::missing_inline_in_public_items)] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result837 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 838 f.debug_struct("OwnedFd").field("fd", &self.fd).finish() 839 } 840 } 841 842 #[cfg(windows)] 843 impl fmt::Debug for OwnedHandle { 844 #[allow(clippy::missing_inline_in_public_items)] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result845 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 846 f.debug_struct("OwnedHandle") 847 .field("handle", &self.handle) 848 .finish() 849 } 850 } 851 852 #[cfg(windows)] 853 impl fmt::Debug for OwnedSocket { 854 #[allow(clippy::missing_inline_in_public_items)] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result855 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 856 f.debug_struct("OwnedSocket") 857 .field("socket", &self.socket) 858 .finish() 859 } 860 } 861