use std::io::{Result, Read, Write, copy, stdout, stderr};
use std::env::args_os;
use std::process::exit;
use std::ffi::OsString;
use std::fs::File;
use std::path::Path;

extern crate concat;
use concat::concat;

fn main() {
    let mut args = args_os();
    let progname = args.next().unwrap_or_else(|| OsString::from("cat"));

    let mut c = concat(args.map(InputSource::from));
    let res = copy(&mut c, &mut stdout());

    if let Err(e) = res {
        match c.current() {
            None => {
                writeln!(&mut stderr(),
                         "{}: {}\n",
                         AsRef::<Path>::as_ref(&progname).display(),
                         e).unwrap();
            },

            Some(ref f) => {
                writeln!(&mut stderr(),
                         "{}: {}: {}\n",
                         AsRef::<Path>::as_ref(&progname).display(),
                         f.path().display(),
                         e).unwrap();
            },
        };

        exit(1);
    }
}

struct InputSource {
    path: OsString,
    file: Option<File>,
}

impl InputSource {
    pub fn 
(&self) -> &Path {
        self.path.as_ref()
    }
}

impl From<OsString> for InputSource {
    fn from(path: OsString) -> InputSource {
        InputSource {
            path: path,
            file: None,
        }
    }
}

impl Read for InputSource {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        if self.file.is_none() {
            self.file = Some(try!(File::open(&self.path)));
        }

        self.file.as_mut().unwrap().read(buf)
    }
}

path