xio_webapi 0.19.0

XIO web API data structures
Documentation
#[macro_use]
extern crate snafu;

extern crate serde_json;
extern crate structopt;
extern crate xio_webapi;

use snafu::{Backtrace, ResultExt};
use std::fs::File;
use std::io::{BufRead, BufReader};
use structopt::StructOpt;
use xio_webapi::JobEvent;

#[derive(Debug, Snafu)]
enum Error {
    #[snafu(display("Deserialization failed {}", source))]
    LineDeserialization {
        source: serde_json::Error,
        backtrace: Backtrace,
    },
    /// A file open error happened.
    #[snafu(display("Couldn't open file {}: {}", path.display(), source))]
    FileOpen {
        /// The affected path.
        path: std::path::PathBuf,
        /// The source of the error.
        source: std::io::Error,
        /// The captured backtrace
        backtrace: Backtrace,
    },
    /// An error happend during reading from file.
    #[snafu(display("Couldn't read from file {}: {}", path.display(), source))]
    FileRead {
        /// The affected path.
        path: std::path::PathBuf,
        /// The source of the error.
        source: std::io::Error,
        /// The captured backtrace
        backtrace: Backtrace,
    },
}

type Result<T, E = Error> = std::result::Result<T, E>;

#[derive(StructOpt, Debug)]
#[structopt(name = "xio-check-joblog")]
struct Arguments {
    file: String,
}

fn load_line(line: &str) -> Result<JobEvent> {
    serde_json::from_str(line).context(LineDeserialization {})
}

/// Returns the number of errors found in the line.
fn check_line(number: usize, line: &str) -> usize {
    match load_line(line) {
        Ok(_) => 0usize,
        Err(e) => {
            eprintln!("Error in line {}: {}", number, e,);
            1usize
        }
    }
}

fn run() -> Result<usize> {
    let arguments = Arguments::from_args();
    println!("Checking file {}", arguments.file);

    let path = std::path::PathBuf::from(arguments.file);

    let file = File::open(&path).context(FileOpen {
        path: path.to_path_buf(),
    })?;

    let mut count = 0usize;
    for (number, line) in BufReader::new(file).lines().enumerate() {
        count += check_line(
            number + 1,
            &line.context(FileRead {
                path: path.to_path_buf(),
            })?,
        );
    }

    if count == 0usize {
        println!("File OK");
    } else {
        println!("Found {} errors", count);
    }
    Ok(count)
}

fn main() -> Result<()> {
    use std::process::exit;
    let res = run();
    match &res {
        Ok(c) if *c == 0usize => exit(0),
        Ok(_) => exit(1),
        Err(_) => {}
    };
    res.map(|_| ())
}