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}