io_result_ext/
lib.rs

1//! Provides [`IoResultExt`], an extension trait for shortening common patterns with [`std::io::Result`].
2#![deny(missing_docs)]
3
4use std::io;
5
6/// A collection of helper methods for [`std::io::Result`].
7pub trait IoResultExt<T>: sealed::Sealed + Sized {
8    /// Map potentially [not found](`std::io::ErrorKind::NotFound`) entities to an [`Option`].
9    ///
10    /// ```
11    /// # use std::fs::File;
12    /// # use io_result_ext::IoResultExt;
13    /// if let Some(config) = File::open("config.json").optional()? {
14    ///     // do something...
15    /// }
16    /// # Ok::<(), std::io::Error>(())
17    /// ```
18    fn optional(self) -> io::Result<Option<T>>;
19
20    /// Mask [`ErrorKind::AlreadyExists`](`std::io::ErrorKind::AlreadyExists`) errors.
21    ///
22    /// ```
23    /// # use std::fs;
24    /// # use io_result_ext::IoResultExt;
25    /// # fn test() -> std::io::Result<()> {
26    /// fs::create_dir("cache").can_exist()?;
27    /// // And then on a later run...
28    /// fs::create_dir("cache").can_exist()?;
29    /// # Ok(())
30    /// # }
31    /// ```
32    fn can_exist(self) -> Self
33    where
34        T: Default;
35}
36
37impl<T> IoResultExt<T> for io::Result<T> {
38    fn optional(self) -> io::Result<Option<T>> {
39        match self {
40            Ok(t) => Ok(Some(t)),
41            Err(ref e) if e.kind() == io::ErrorKind::NotFound => Ok(None),
42            Err(e) => Err(e),
43        }
44    }
45
46    fn can_exist(self) -> Self
47    where
48        T: Default,
49    {
50        match self {
51            Ok(t) => Ok(t),
52            Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(T::default()),
53            Err(e) => Err(e),
54        }
55    }
56}
57
58mod sealed {
59    /// Prevent accidental implementations of other traits on external types.
60    ///
61    /// For more information, see the [Rust API guidelines](https://rust-lang.github.io/api-guidelines/future-proofing.html).
62    pub trait Sealed {}
63
64    impl<T> Sealed for ::std::io::Result<T> {}
65}