hyper_archive/
lib.rs

1use std::sync::Arc;
2use base64::{engine::general_purpose, Engine as _};
3use lz4_flex;
4use tokio;
5use tokio::fs::{try_exists, File, OpenOptions};
6use tokio::io::{AsyncReadExt, AsyncWriteExt};
7
8async fn lz4_compress(data: Vec<u8>) -> String {
9    let data = Arc::new(data);
10    let output = tokio::task::spawn_blocking(move || {
11        let out_first = lz4_flex::compress_prepend_size(&data);
12        general_purpose::STANDARD.encode(out_first)
13    });
14
15    output.await.unwrap_or_else(|e1| panic!("There was an error while Compression task: {e1}"))
16}
17
18async fn lz4_decompress(data: String) -> Vec<u8> {
19    let output = tokio::task::spawn_blocking(move || {
20        let out_first = general_purpose::STANDARD.decode(&data).unwrap_or_else(|e| {panic!("There was an error while Base64 decoding progress: {e}")});
21        lz4_flex::decompress_size_prepended(out_first.as_slice()).unwrap_or_else(|e| panic!("There was an error while decompressing file: {e}"))
22    });
23
24    output.await.unwrap_or_else(|e1| panic!("There was an error while Compression task: {e1}"))
25}
26
27pub async fn write_structure(name: &str, hpa_file: &str) {
28    let mut file = match File::open(name).await {
29        Ok(file) => file,
30        Err(e) => panic!("There was an error while opening file: {e}"),
31    };
32
33    let mut file_data = Vec::new();
34    file.read_to_end(&mut file_data).await.expect("There was an error while reading Data");
35
36    let compressed_data = lz4_compress(file_data).await;
37    let wrs = format!("{name}: {compressed_data};");
38
39    match try_exists(hpa_file).await.unwrap() {
40        true => panic!("File already exist"),
41        false => {
42            let mut file = File::create(hpa_file).await.expect("There was an error while Creating file");
43            let _ = file.write_all(wrs.as_bytes()).await;
44        }
45    }
46}
47
48pub async fn find_line(line_to_find: &str, content: String) -> String {
49    let mut final_data = String::new();
50    let data = format!("{line_to_find}: ");
51
52    if let Some(start) = content.find(data.as_str()) {
53        let start_index = start + data.len();
54        if let Some(end) = content[start_index..].find(';') {
55            final_data = content[start_index..start_index + end].to_string();
56        } else {
57            final_data = content[start_index..].to_string();
58        }
59    };
60
61    final_data
62}
63
64pub async fn read_structure(name: &str, hpa_file: &str) -> String {
65    let mut file = File::open(hpa_file).await.expect("There was an error while opening File");
66    let mut file_data = Vec::new();
67    let _ = file.read_to_end(&mut file_data).await.expect("There was an error while reading File");
68
69    let content = String::from_utf8(file_data).expect("There was an error while UTF-8 to String");
70    let final_data = find_line(name, content).await;
71
72    let decompressed_data = lz4_decompress(final_data).await;
73    String::from_utf8(decompressed_data).expect("There was an error while UTF-8 to String")
74}
75
76pub async fn add_structure(data_file_name: &str, hpa_file_name: &str) {
77    let mut data_file = File::open(data_file_name).await.expect("Failed to open data file");
78    let mut data_file_data = Vec::new();
79    data_file.read_to_end(&mut data_file_data).await.expect("Failed to read data file");
80
81    let compressed_data = lz4_compress(data_file_data).await;
82
83    let mut hpa_file = File::open(hpa_file_name).await.expect("Failed to open HPA file");
84    let mut hpa_file_data = Vec::new();
85    hpa_file.read_to_end(&mut hpa_file_data).await.expect("Failed to read HPA file");
86
87    let mut content = String::from_utf8(hpa_file_data).expect("Invalid UTF-8 sequence");
88
89    if content.contains(data_file_name) {
90        println!("{} is already exist. Do you meant to update?", data_file_name);
91        return;
92    }
93
94    content.push_str(&format!("{data_file_name}: {compressed_data};"));
95
96    let mut hpa_file = OpenOptions::new().write(true).truncate(true).open(hpa_file_name).await.expect("Failed to open HPA file for writing");
97    hpa_file.write_all(content.as_bytes()).await.expect("Failed to write to HPA file");
98}
99
100pub async fn remove_structure(name: &str, hpa_file: &str) {
101    let mut file = File::open(hpa_file).await.expect("Failed to open HPA file");
102    let mut data = Vec::new();
103    file.read_to_end(&mut data).await.expect("Failed to read HPA file");
104
105    let content = String::from_utf8(data).expect("Invalid UTF-8 sequence");
106    let line_to_find = format!("{}: ", name);
107    let mut new_content = String::new();
108
109    if let Some(start) = content.find(&line_to_find) {
110        let end = content[start..].find(';').unwrap_or(content.len() - start) + start;
111        new_content.push_str(&content[..start]);
112        new_content.push_str(&content[end + 1..]);
113    } else {
114        new_content = content;
115    }
116
117    let mut file = OpenOptions::new().write(true).truncate(true).open(hpa_file).await.expect("Failed to open HPA file for writing");
118    file.write_all(new_content.as_bytes()).await.expect("Failed to write to HPA file");
119}
120
121pub async fn update_structure(data_file_name: &str, hpa_file_name: &str) {
122    let mut data_file = File::open(data_file_name).await.expect("Failed to open data file");
123    let mut data_file_data = Vec::new();
124    data_file.read_to_end(&mut data_file_data).await.expect("Failed to read data file");
125
126    let compressed_data = lz4_compress(data_file_data).await;
127
128    let mut hpa_file = File::open(hpa_file_name).await.expect("Failed to open HPA file");
129    let mut hpa_file_data = Vec::new();
130    hpa_file.read_to_end(&mut hpa_file_data).await.expect("Failed to read HPA file");
131
132    let mut content = String::from_utf8(hpa_file_data).expect("Invalid UTF-8 sequence");
133
134    let line_to_find = format!("{}: ", data_file_name);
135
136    if let Some(start) = content.find(&line_to_find) {
137        let end = content[start..].find(';').unwrap_or(content.len() - start) + start;
138        content.replace_range(start..end + 1, &format!("{}: {};", data_file_name, compressed_data));
139    } else {
140        content.push_str(&format!("{}: {};", data_file_name, compressed_data));
141    }
142
143    let mut hpa_file = OpenOptions::new().write(true).truncate(true).open(hpa_file_name).await.expect("Failed to open HPA file for writing");
144    hpa_file.write_all(content.as_bytes()).await.expect("Failed to write to HPA file");
145}
146
147pub async fn export_structure(name: &str, hpa_file: &str, file_name: &str) {
148    let data = read_structure(name, hpa_file).await;
149
150    let mut file = File::create(file_name).await.unwrap_or_else(|e| {panic!("There was an error while Creating file")});
151    file.write_all(data.as_bytes()).await.unwrap_or_else(|e1| {panic!("There was an error while Writing data")});
152}