Skip to content

Instantly share code, notes, and snippets.

@tilpner
Last active March 2, 2016 03:13
Show Gist options
  • Save tilpner/250427adeafbf0ef79b7 to your computer and use it in GitHub Desktop.
Save tilpner/250427adeafbf0ef79b7 to your computer and use it in GitHub Desktop.
use std::{env, io, process};
use std::fs::File;
use std::path::Path;
use std::collections::HashSet;
use std::io::{BufReader, BufRead, Write};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
enum Errors {
Success = 0,
Open = 1,
Directory = 2,
Inexistent = 4,
}
// This doesn't get any prettier. At this point, it should be split
// and using error propagation. But this is an example, so it won't.
fn main() {
let (out, mut err) = (io::stdout(), io::stderr());
let mut errors = HashSet::with_capacity(32);
let (args, files): (Vec<_>, Vec<_>) = env::args_os()
.skip(1)
.map(|s| s.to_string_lossy().into_owned())
.partition(|a| a == &"-n");
let linenumbers = !args.is_empty();
for arg in files {
let path = Path::new(&arg);
if path.is_file() {
match File::open(&path) {
Ok(ref mut file) if linenumbers => {
let buf = BufReader::new(file);
let mut out = out.lock();
for (num, line) in buf.lines().enumerate() {
writeln!(out, "{:8x} {}", num, line.expect("Couldn't read file"))
.expect("Couldn't write to stdout");
}
}
Ok(ref mut file) => {
let mut out = out.lock();
io::copy(file, &mut out).expect("Couldn't read file");
}
Err(e) => {
writeln!(err, "{}: {}", arg, e).expect("Couldn't write to stdout");
errors.insert(Errors::Open);
}
}
} else if path.is_dir() {
writeln!(err, "{}: Is a directory", arg).expect("Couldn't write to stdout");
errors.insert(Errors::Directory);
} else {
writeln!(err, "{}: No such file or directory", arg).expect("Couldn't write to stdout");
errors.insert(Errors::Inexistent);
}
}
let exit_code = errors.iter().fold(Errors::Success as i32, |a, &b| a | b as i32);
process::exit(exit_code as i32);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment