tla/
lib.rs

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)) // 0: dir, 1: file
43        .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}