main/
main.rs

1mod errors {
2    // errors.rs
3    use failchain::{BoxedError, ChainErrorKind};
4    use failure::Fail;
5    use std::path::PathBuf;
6    use std::result::Result as StdResult;
7
8    pub type Error = BoxedError<ErrorKind>; // Use `UnboxedError` instead for
9                                            // non-allocating, but bigger `Error`.
10    pub type Result<T> = StdResult<T, Error>;
11
12    #[derive(Clone, Eq, PartialEq, Debug, Fail)]
13    pub enum ErrorKind {
14        #[fail(display = "Metadata I/O error {:?}.", 0)]
15        MetadataIo(PathBuf),
16
17        #[fail(display = "Corrupt metadata file: {}", 0)]
18        CorruptMetadata(String),
19
20        #[fail(display = "WAD I/O error {:?}.", 0)]
21        WadIo(PathBuf),
22
23        #[fail(display = "Corrupt WAD file: {}", 0)]
24        CorruptWad(String),
25    }
26
27    impl ChainErrorKind for ErrorKind {
28        type Error = Error;
29    }
30}
31
32mod main {
33    // main.rs
34    use super::errors::{ErrorKind, Result};
35    use failchain::{
36        bail,
37        ensure,
38        ResultExt, // for `chain_err`,
39    };
40    use std::fs::File;
41    use std::io::Read;
42    use std::path::Path;
43
44    fn validate_metadata(path: &Path, metadata: &str) -> Result<()> {
45        // `ensure` is like `assert` (or failure's ensure), except it allows you to
46        // specify the `ErrorKind`.
47        ensure!(
48            !metadata.is_empty(),
49            ErrorKind::CorruptMetadata(format!("metadata file {:?} is empty", path))
50        );
51
52        // a special mode of `ensure` works for functions that return `ErrorKind`-s
53        // and take a single string as argument:
54        ensure!(
55            metadata.len() > 100,
56            ErrorKind::CorruptMetadata, // Any FnOnce(String) -> ErrorKind
57            "metadata file {:?} is too long", // Rest of arguments are format args.
58            path,
59        );
60
61        // `bail` is like `ensure`, but without the condition and always returns
62        // early.
63        bail!(
64            ErrorKind::CorruptMetadata,
65            "validation isn't actually implemented"
66        );
67    }
68
69    fn load(wad: &Path, metadata: &Path) -> Result<()> {
70        // `chain_err` stashes the original error as the `cause` of a new error.
71        let wad_file = File::open(wad).chain_err(|| ErrorKind::WadIo(wad.to_owned()))?;
72
73        let mut metadata_content = String::new();
74
75        // `chain_inspect_err` stashes the original error as the `cause` of the new
76        // error, but it first allows the callback to inspect it.
77        let metadata_file = File::open(metadata)
78            .and_then(|mut file| file.read_to_string(&mut metadata_content))
79            .chain_inspect_err(|_io_error| ErrorKind::MetadataIo(metadata.to_owned()))?;
80
81        validate_metadata(metadata, &metadata_content)?;
82
83        Ok(())
84    }
85}
86
87fn main() {}