1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
extern crate size_format;

use size_format::SizeFormatterBinary;
use std::env::args;
use std::io::{stdin, Read};
use std::path::Path;

fn main() -> Result<(), String> {
    let mut args: Vec<String> = args().collect();
    args.remove(0);

    if args.len() >= 2 {
        return show_msg(MsgType::InvalidArgumentCount(args.len()));
    }

    struct Arguments {
        human_readable: bool,
    }
    let mut arguments = Arguments {
        human_readable: false,
    };

    if args.len() == 1 {
        let option = &args[0];
        match option.as_str() {
            "-h" | "--human-readable" => {
                arguments.human_readable = true;
            }
            "--help" => {
                return show_msg(MsgType::Help);
            }
            _ => {
                return show_msg(MsgType::UnknownOption(option));
            }
        }
    }

    let mut stdin = stdin();
    let mut buf = [0_u8; 4096];
    let mut size_sum = 0_usize;
    loop {
        let r = stdin.read(&mut buf).unwrap();
        size_sum += r;
        if r == 0 {
            break;
        }
    }

    if arguments.human_readable {
        let size = SizeFormatterBinary::new(size_sum as u64).to_string();
        println!("{}B", size);
    } else {
        println!("{}", size_sum);
    }
    Ok(())
}

enum MsgType<'a> {
    Help,
    InvalidArgumentCount(usize),
    UnknownOption(&'a String),
}

fn show_msg(msg_type: MsgType) -> Result<(), String> {
    return match msg_type {
        MsgType::Help => {
            let mut args = args();
            let file_path = args.next().unwrap();
            let file_name = Path::new(&file_path).file_name().unwrap().to_str().unwrap();

            println!(
                "Print the size of all data read from stdin.
Usage: {0} [option]
Options:
  -h, --human-readable  Print human-readable size format.
  --help  Show this help.",
                file_name
            );
            Ok(())
        }
        MsgType::InvalidArgumentCount(c) => Err(format!("Invalid argument count: {}", c)),
        MsgType::UnknownOption(o) => Err(format!("Unknown option: {}", o)),
    };
}