close_err/
lib.rs

1//! Exposes a `close` method on files, to permit finer grained error handling.
2//!
3//! ```
4//! use close_err::Closable;
5//! use std::{fs::File, io::Write};
6//!
7//! let mut f = File::create("abc.txt").unwrap();
8//! f.write_all("hello".as_bytes());
9//! f.close().unwrap();
10//! ```
11
12use std::io;
13
14pub trait Closable {
15    fn close(self) -> Result<(), io::Error>;
16}
17
18#[cfg(unix)]
19impl<T> Closable for T
20where
21    T: std::os::unix::io::IntoRawFd,
22{
23    fn close(self) -> Result<(), io::Error> {
24        let fd = self.into_raw_fd();
25        let rc = unsafe { libc::close(fd) };
26        bool_to_last_error(rc == 0)
27    }
28}
29
30#[cfg(windows)]
31impl<T> Closable for T
32where
33    T: std::os::windows::io::IntoRawHandle,
34{
35    fn close(self) -> Result<(), io::Error> {
36        let handle = self.into_raw_handle();
37        let rc = unsafe { kernel32::CloseHandle(handle) };
38        bool_to_last_error(rc != 0)
39    }
40}
41
42fn bool_to_last_error(b: bool) -> Result<(), io::Error> {
43    b
44        .then_some(())
45        .ok_or_else(io::Error::last_os_error)
46}