1use std::fs;
2use aoko::no_std::pipelines::{pipe::Pipe, tap::Tap};
3use caesar::Caesar;
4use multi::{mt_enc, mt_dec};
5use rayon::{slice::ParallelSlice, prelude::ParallelIterator};
6use tar::{Builder, Archive};
7use ades::{Padding, aes_enc, aes_dec, des_enc, des_dec};
8
9pub mod cli;
10pub mod caesar;
11pub mod multi;
12
13fn padding<R>(aes: &str, des: &str, f: impl FnOnce(&[u8], &[u8]) -> R) -> R {
14 aes.padding(32).as_bytes().pipe(|aes_key|
15 des.padding(24).as_bytes().pipe(|des_key|
16 f(aes_key, des_key)
17 ))
18}
19
20fn mark_file_or_dir(r#in: &str, vec: &mut Vec<u8>) {
21 let meta = fs::metadata(r#in).unwrap();
22 if meta.is_dir() {
23 vec.push(0)
24 } else if meta.is_file() {
25 vec.push(1)
26 } else {
27 panic!("unsupported file type")
28 }
29}
30
31const GROUP: usize = 2 * 1024 * 1024 * 1024 - 1;
32
33pub fn compress_and_encrypt(r#in: &str, aes: &str, des: &str) {
34 Builder::new(vec![])
35 .tap_mut(|b| b.append_dir_all("", r#in).unwrap_or_else(|_| b.append_path(r#in).unwrap()))
36 .pipe(|b| b.into_inner().unwrap())
37 .pipe_ref(|data| mt_enc(data))
38 .cs_enc(175)
39 .par_chunks(GROUP)
40 .flat_map(|slice| padding(aes, des, |aes, des| aes_enc(aes)(slice).pipe(|ctx| des_enc(des)(&ctx))))
41 .collect::<Vec<_>>()
42 .tap_mut(|vec| mark_file_or_dir(r#in, vec)) .pipe(|byt| fs::write(format!("{in}.tla"), byt.cs_enc(23)).unwrap())
44}
45
46fn judge_file_or_dir(last: u8, byt: Vec<u8>, f1: impl FnOnce(&mut Archive<&[u8]>), f2: impl FnOnce(&mut Archive<&[u8]>)) {
47 let tar = &mut Archive::new(byt.as_slice());
48 match last {
49 0 => f1(tar),
50 1 => f2(tar),
51 _ => panic!("file type error")
52 }
53}
54
55pub fn decrypt_and_decompress(r#in: &str, aes: &str, des: &str) {
56 let mut read = fs::read(r#in).unwrap().cs_dec(23);
57 let last = read.pop().unwrap();
58
59 read.par_chunks(GROUP)
60 .flat_map(|slice| padding(aes, des, |aes, des| des_dec(des)(slice).pipe(|ctx| aes_dec(aes)(&ctx))))
61 .collect::<Vec<_>>()
62 .cs_dec(175)
63 .pipe_ref(|data| mt_dec(data))
64 .pipe(|byt| r#in.trim_end_matches(".tla").pipe(|name|
65 judge_file_or_dir(last, byt, |tar| tar.unpack(name).unwrap(),
66 |tar| tar.entries().unwrap().for_each(|file| {
67 file.unwrap()
68 .unpack(name).unwrap();
69 })
70 )
71 ))
72}