core-utils 0.1.2

A reimplementation of the GNU core utils in the Rust programming language
// Copyright (C) 2015, Alberto Corona <ac@albertocorona.com>
// All rights reserved. This file is part of core-utils, distributed under the
// GPL v3 license. For full terms please see the LICENSE file.

#![crate_type = "bin"]
#![crate_name = "cat"]

static UTIL: Prog = Prog { name: "cat", vers: "0.1.0", yr: "2015" };
static SM_BUFF_SIZE: usize = 256;
static LRG_BUFF_SIZE: usize = 64 * 1024;

extern crate pgetopts;
extern crate rpf;

use pgetopts::{Options};
use rpf::{Status,Styled,Prog};

use std::env;
use std::iter;
use std::io::{self,Read, Write};
use std::path::{Path};
use std::fs::{File};

fn write_bytes(mut file: File) {
    let mut out = &mut io::stdout();
    let buffer = &mut vec![0; SM_BUFF_SIZE];
    loop {
        let read = match file.read(buffer) {
            Ok(c) => { c },
            Err(e) => {
                Status::Error.err(UTIL.name, e.to_string());
                panic!();
            }
        };
        if read == 0 {
            break;
        }
        match out.write_all(&buffer[..read]) {
            Ok(w) => { w },
            Err(e) => {
                Status::Error.err(UTIL.name, e.to_string());
                panic!();
            }
        };
        if read == buffer.len() && read < LRG_BUFF_SIZE {
            buffer.extend(iter::repeat(0).take(read));
        }
    }
}

fn read_files<P: AsRef<Path>>(files: Vec<P>) {
    for item in files {
        let file = match File::open(&item) {
            Ok(f) => { f },
            Err(e) => {
                Status::Error.err(UTIL.name, e.to_string());
                panic!();
            }
        };
        write_bytes(file);
    }
}

fn print_usage(opts: Options) {
    print!("{}: {} {}... {}...\n\
    Concatenate FILE(s) to standard output", "Usage".bold(), UTIL.name.bold(),
    "[OPTION]".underline(), "FILE".underline());
    println!("{}", opts.options());
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();

    opts.optflag("h", "help", "Print help information");
    opts.optflag("", "version", "Print version information");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => {
            Status::Error.err(UTIL.name, f.to_string());
            panic!(f)
        }
    };
    if matches.opt_present("h") {
        print_usage(opts);
    } else if matches.opt_present("version") {
        UTIL.copyright("Copyright (C) 2015 core-utils developers\n\
                       License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n\
                       This is free software: you are free to change and redistribute it.\n\
                       There is NO WARRANTY, to the extent permitted by law.\n\n",
                       vec!["Alberto Corona"]);
    } else {
        read_files(matches.free);
    }
}