hashkitten/
lib.rs

1use std::fs;
2use std::fs::File;
3use std::io;
4use std::io::Write;
5
6mod funcs;
7
8const HELP: &str = "\n  /l、
9(゚、 。 7
10  l  ~ヽ
11  じしf_,)ノ\n\n\
12Welcome to hashkitten! 🐾\n\
13Your purrfect hashing companion.\n\n\
14Usage: hashkitten [-h] [-f FILE] [-c FILE|\"TEXT\" HASH] [\"TEXT\"]\n\
15A fun tool for hashing text or files.\n\n\
16ARGUMENTS\n\
17    -h | --help: Print help and exit\n\
18    -f | --file FILE [OUTPUT]: Hash the contents of the specified file. Optionally, write the hash to OUTPUT.\n\
19    -c | --compare FILE|\"TEXT\" HASH: Compare the contents of a file or a message to the specified hash.\n\
20    \"TEXT\": Input text to be hashed (must be enclosed in double quotes).\n\n\
21EXAMPLES\n\
22    hashkitten -h                        # Display help\n\
23    hashkitten -f input.txt              # Hash the contents of input.txt\n\
24    hashkitten -f input.txt output.txt   # Hash the contents of input.txt and write the hash to output.txt\n\
25    hashkitten -c input.txt HASH         # Compare the hash of input.txt with HASH\n\
26    hashkitten -c \"Hello, world!\" HASH  # Compare the hash of the message with HASH\n\
27    hashkitten \"Hello, world!\"          # Hash the given text (must be in quotes)\n";
28
29pub fn meow_message(message: String) -> String {
30    let message_bytes = funcs::pre_processing(message);
31    let message_schedule = funcs::create_message_schedule(message_bytes);
32    let hash_values = funcs::compressing_schedule(message_schedule);
33    let sha256_hash = funcs::concatenate_hash(hash_values);
34    let meow = funcs::meow_from_hash(&sha256_hash);
35
36    meow
37}
38
39fn read_file(file_path: &String) -> Result<String, io::Error> {
40    match fs::read_to_string(file_path) {
41        Ok(val) => Ok(val),
42        Err(e) => Err(e),
43    }
44}
45
46pub fn run(args: Vec<String>) {
47    if args.len() < 2 {
48        eprintln!(
49            "*confused meow* No arguments provided! Use `-h` or `--help` for usage instructions."
50        );
51        return;
52    }
53
54    match args.get(1).map(|s| s.as_str()) {
55        Some("-h") | Some("--help") => {
56            println!("{}", HELP);
57        }
58
59        Some("-f") | Some("--file") => {
60            if args.len() < 3 {
61                eprintln!("*confused meow* Missing file path! Use `-f FILE` to specify a file.");
62                return;
63            }
64            let file_path = &args[2];
65            let output = args.get(3).map(String::from);
66            match read_file(file_path) {
67                Ok(contents) => {
68                    let hash = meow_message(contents);
69                    if let Some(output_path) = output {
70                        match File::create(&output_path) {
71                            Ok(mut file) => {
72                                if let Err(e) = file.write_all(hash.as_bytes()) {
73                                    eprintln!(
74                                        "*surprised meow* Failed to write hash to file: {}",
75                                        e
76                                    );
77                                }
78                            }
79                            Err(e) => {
80                                eprintln!("*surprised meow* Failed to create file: {}", e);
81                            }
82                        }
83                    } else {
84                        println!("{}", hash);
85                    }
86                }
87                Err(e) => {
88                    eprintln!("*confused meow* Could not read file: {}", e);
89                }
90            }
91        }
92
93        Some("-c") | Some("--compare") => {
94            if args.len() < 4 {
95                eprintln!("*confused meow* Missing arguments for comparison! Use `-c \"MESSAGE\" HASH` or `-c FILE HASH`.");
96                return;
97            }
98
99            let input = args[2].clone();
100            let hash = args[3].clone();
101
102            let message = match read_file(&input) {
103                Ok(contents) => contents,
104                Err(_) => input,
105            };
106
107            let calculated_hash = meow_message(message);
108
109            if calculated_hash == hash {
110                println!("*excited purrs* Meow meow! The hash matches purrfectly! 🐱✨");
111            } else {
112                println!("*sad meow* The hash doesn't match! 🐱💔");
113            }
114        }
115
116        Some(_) => {
117            let message = args[1..].join(" ");
118            println!("{}", meow_message(message));
119        }
120
121        None => {
122            eprintln!("*confused meow* No valid arguments provided! Use `-h` for help.");
123        }
124    }
125}