1use std::fs::{self, File, OpenOptions};
2use std::io::{BufRead, BufReader, Write};
3
4pub struct TNT {
5 filename: String,
6}
7
8impl TNT {
9 pub fn connect(filename: &str) -> Self {
31
32 if fs::metadata(filename).is_err() {
33 File::create(filename).expect("File creation error!");
34 }
35
36 Self { filename: filename.to_string()}
37 }
38
39 fn is_ccf(&self) -> std::io::Result<bool> {
40 let file = File::open(&self.filename)?;
41 let reader = BufReader::new(&file);
42 let mut is_good = false;
43 let mut brack = 0;
44 let mut rev_brack = 0;
45 let mut braces = 0;
46 let mut rev_braces = 0;
47
48 for line in reader.lines() {
49 let line = line?;
50
51 if line.find('(').is_some() {
52 brack += 1;
53 }
54
55 if line.find(')').is_some() {
56 rev_brack += 1;
57 }
58
59 if line.find('{').is_some() {
60 braces += 1;
61 }
62
63 if line.find('}').is_some() {
64 rev_braces += 1;
65 }
66 }
67
68 if brack == rev_brack && braces == rev_braces {
69 is_good = true;
70 }
71
72 Ok(is_good)
73 }
74
75 fn get_var_line(&self, key: &str, var: &str) -> std::io::Result<i32> {
76 let file = File::open(&self.filename)?;
77 let reader = BufReader::new(&file);
78 let mut is_key = false;
79 let mut var_line: i32 = -1;
80
81 for (i, line) in reader.lines().enumerate() {
82 let line = line?;
83
84 if line.find('(').is_some() {
85 let cleaned_line = line.replace(['(', ')', '{'], "");
86 let k = cleaned_line.trim();
87
88 if k == key {
89 is_key = true;
90 continue;
91 }
92 }
93
94 if is_key && line.find('}').is_some() {
95 break;
96 }
97
98
99 if is_key {
100 let fmt_line = line.trim();
101 let var_from_line = fmt_line.split('=').next().unwrap_or(fmt_line);
102
103 if var_from_line == var.trim() {
104 var_line = i as i32;
105 break;
106
107 }
108 }
109
110 }
111
112 Ok(var_line)
113 }
114
115 fn is_var(&self, key: &str, var: &str) -> std::io::Result<bool> {
116 let file = File::open(&self.filename)?;
117 let reader = BufReader::new(&file);
118 let mut is_varible = false;
119 let mut is_found_key = false;
120 let mut var_val = String::new();
121
122 for line in reader.lines() {
123 let line = line?;
124
125 if line.find('(').is_some() {
126 let cleaned_line = line.replace(['(', ')', '{'], "");
127 let k = cleaned_line.trim();
128
129 if k == key.trim() {
130 is_found_key = true;
131 continue;
132 }
133 }
134
135 if is_found_key && line.find('}').is_some() {
136 break;
137 }
138
139 if is_found_key {
140 let fmt_line = line.trim();
141 var_val.push_str(&format!("{},", fmt_line));
142 }
143 }
144
145 let old_var: Vec<&str > = var_val.split(',').filter(|s| !s.is_empty()).collect();
146
147 for v in old_var {
148 let v_v = v.split('=').next().unwrap_or(v);
149
150 if v_v == var.trim() {
151 is_varible = true;
152 break;
153 }
154 }
155
156 Ok(is_varible)
157
158 }
159
160 pub fn add<T: std::fmt::Display, V: std::fmt::Display>(&self, key: &str, var: T, val: V) -> std::io::Result<()> {
176 let var_str = var.to_string();
177 let val_str = val.to_string();
178
179 if !self.is_ccf()? {
180 println!("File integrity error!");
181 return Ok(());
182 }
183
184 let file = File::open(&self.filename)?;
185 let reader = BufReader::new(&file);
186 let mut is_found = false;
187 let mut is_not_key = true;
188 let mut new_text: String = String::new();
189
190 for line in reader.lines() {
191 let line = line?;
192
193 if line.find('(').is_some() {
194 let cleaned_line = line.replace('(', "").replace(')', "").replace('{', "");
195 let k = cleaned_line.trim();
196
197 if k == key {
198 is_found = true;
199 is_not_key = false;
200 }
201 }
202
203 if line.find('}').is_some() && is_found {
204 let is_val = self.is_var(key, var_str.as_str())?;
205
206 if is_val {
207 println!("A variable named '{}' already exists!", var_str);
208 return Ok(());
209 }
210
211 new_text.push_str(&format!("\t{}={}\n", var_str, val_str));
212 is_found = false;
213 }
214
215 new_text.push_str(&line);
216 new_text.push_str("\n");
217
218 }
219
220 if is_not_key {
221 new_text.push_str(&format!("({}) {{\n\t{}={}\n}}", key, var_str, val_str));
222 }
223
224
225 let mut file = fs::OpenOptions::new().write(true).truncate(true).create(true).open(&self.filename)?;
226 write!(file, "{}", new_text)?;
227
228 Ok(())
229 }
230
231 pub fn get<T: std::fmt::Display>(&self, key: &str, var: T) -> std::io::Result<String> {
245 let var_str = var.to_string();
246
247 if !self.is_ccf()? {
248 println!("File integrity error!");
249 return Ok("Error".to_string());
250 }
251
252 let file = fs::File::open(&self.filename)?;
253 let reader = BufReader::new(&file);
254 let mut is_key = false;
255 let mut fmt_val = String::new();
256
257
258 for line in reader.lines() {
259 let line = line?;
260
261 if line.find('(').is_some() {
262 let cleaned_line = line.replace(['(', ')', '{'], "");
263 let k = cleaned_line.trim();
264
265 if k == key {
266 is_key = true;
267 continue;
268 }
269 }
270
271 if is_key && line.find('}').is_some() {
272 println!("The variable was not found!");
273 break;
274 }
275
276
277 if is_key {
278 if let Some((name, val)) = line.trim().split_once("=") {
279 if name == var_str.trim() {
280 fmt_val.push_str(val);
281 break;
282 }
283 }
284 }
285
286 }
287
288
289 if fmt_val.is_empty() {
290 fmt_val.push_str("NONE_VAL");
291 }
292
293 Ok(fmt_val)
294
295 }
296
297 pub fn edit<T: std::fmt::Display, V: std::fmt::Display>(&self, key: &str, var: T, new_val: V) -> std::io::Result<()> {
313 let var_str = var.to_string();
314 let val_str = new_val.to_string();
315
316 if !self.is_ccf()? {
317 println!("File integrity error!");
318 return Ok(());
319 }
320
321 let file = File::open(&self.filename)?;
322 let reader = BufReader::new(&file);
323 let pos = self.get_var_line(key, var_str.as_str())?;
324 let mut txt = String::new();
325
326 if pos == -1 {
327 println!("The variable was not found!");
328 return Ok(());
329 }
330
331 for (i, line) in reader.lines().enumerate() {
332 let line = line?;
333
334 if i as i32 == pos {
335 txt.push_str(&format!("\t{}={}\n", var_str, val_str));
336 continue;
337 }
338
339 txt.push_str(&line);
340 txt.push_str("\n");
341 }
342
343 let mut file = fs::OpenOptions::new().write(true).truncate(true).create(true).open(&self.filename)?;
344 write!(file, "{}", txt)?;
345
346 Ok(())
347 }
348
349 pub fn delete_var<T: std::fmt::Display>(&self, key: &str, var: T) -> std::io::Result<()> {
363 let var_str = var.to_string();
364
365 if !self.is_ccf()? {
366 println!("File integrity error!");
367 return Ok(());
368 }
369
370 let file = File::open(&self.filename)?;
371 let reader = BufReader::new(&file);
372 let mut txt = String::new();
373 let var_del_line = self.get_var_line(key, var_str.as_str())?;
374
375 if var_del_line == -1 {
376 println!("The variable was not found!");
377 return Ok(());
378 }
379
380 for (i, line) in reader.lines().enumerate() {
381 let line = line?;
382
383 if i == var_del_line as usize {
384 continue;
385 }
386
387 txt.push_str(&line);
388 txt.push_str("\n");
389 }
390
391 let mut file = fs::OpenOptions::new().write(true).truncate(true).create(true).open(&self.filename)?;
392 write!(file, "{}", txt)?;
393
394 Ok(())
395 }
396
397 pub fn delete_key(&self, key: &str) -> std::io::Result<()> {
409
410 if !self.is_ccf()? {
411 println!("File integrity error!");
412 return Ok(());
413 }
414
415 let file = File::open(&self.filename)?;
416 let reader = BufReader::new(&file);
417 let mut txt = String::new();
418 let mut is_found_key = false;
419 let mut is_key = false;
420
421 for line in reader.lines() {
422 let line = line?;
423
424 if line.find('(').is_some() {
425 let cleaned_line = line.replace(['(', ')', '{'], "");
426 let k = cleaned_line.trim();
427
428 if k == key.trim() {
429 is_key = true;
430 is_found_key = true;
431 continue;
432 }
433 }
434
435 if is_key && line.find('}').is_some() {
436 is_key = false;
437 continue;
438 }
439
440 if is_key {
441 continue;
442 }
443
444 txt.push_str(&line);
445 txt.push_str("\n");
446 }
447
448 if is_found_key {
449 let mut file = fs::OpenOptions::new().write(true).truncate(true).create(true).open(&self.filename)?;
450 write!(file, "{}", txt)?;
451 }
452
453 Ok(())
454 }
455
456 pub fn clear(&self) -> std::io::Result<()> {
460 File::create(&self.filename)?;
461 Ok(())
462 }
463
464 pub fn get_all(&self, key: &str) -> std::io::Result<Vec<String>> {
474
475 if !self.is_ccf()? {
476 println!("File integrity error!");
477 return Ok(vec!["".to_string()]);
478 }
479
480 let file = File::open(&self.filename)?;
481 let reader = BufReader::new(&file);
482 let mut all_val: Vec<String> = Vec::new();
483 let mut is_key = false;
484
485 for line in reader.lines() {
486 let line = line?;
487
488 if line.find('(').is_some() {
489 let cleaned_line = line.replace(['(', ')', '{'], "");
490 let k = cleaned_line.trim();
491
492 if k == key.trim() {
493 is_key = true;
494 continue;
495 }
496 }
497
498 if is_key && line.find('}').is_some() {
499 break;
500 }
501
502 if is_key {
503 let fmt_line = line.split('=').nth(1).unwrap_or("");
504 let val_fmt = fmt_line.trim().to_string();
505 all_val.push(val_fmt);
506 }
507 }
508
509 Ok(all_val)
510
511 }
512
513 pub fn to_toml(&self, filename: &str) -> std::io::Result<()> {
523
524 if !self.is_ccf()? {
525 println!("File integrity error!");
526 return Ok(());
527 }
528
529 let file = File::open(&self.filename)?;
530 let reader = BufReader::new(&file);
531 let mut is_key = false;
532 let mut txt: String = String::new();
533
534 for line in reader.lines() {
535 let line = line?;
536
537 if line.find('(').is_some() {
538 let cleaned_line = line.replace(['(', ')', '{'], "");
539 let key = cleaned_line.trim();
540 txt.push_str(&format!("[{}]\n", key));
541 is_key = true;
542 continue;
543 }
544
545 if is_key && line.find('}').is_some() {
546 is_key = false;
547 txt.push_str("\n");
548 continue;
549 }
550
551 if is_key {
552 let fmt_val = line.trim();
553 let var = fmt_val.split('=').next().unwrap_or(fmt_val);
554 let val = fmt_val.split('=').nth(1).unwrap_or("");
555 txt.push_str(&format!("{}=\"{}\"\n", var, val));
556 }
557
558 }
559
560 let full_filename = String::from(&format!("{}.toml", filename));
561 let mut file = fs::OpenOptions::new().write(true).truncate(true).create(true).open(full_filename)?;
562 write!(file, "{}", txt)?;
563
564 Ok(())
565 }
566
567 pub fn to_json(&self, filename: &str) -> std::io::Result<()> {
577
578 if !self.is_ccf()? {
579 println!("File integrity error!");
580 return Ok(());
581 }
582
583 let file = File::open(&self.filename)?;
584 let reader = BufReader::new(&file);
585 let mut txt: String = String::new();
586 let mut is_key: bool = false;
587 let mut val_str = String::new();
588
589 txt.push_str("{\n");
590
591 for line in reader.lines() {
592 let line = line?;
593
594 if line.find('(').is_some() {
595 let cleaned_line = line.replace(['(', ')', '{'], "");
596 let key = cleaned_line.trim();
597 txt.push_str(&format!("\t\"{}\": {{\n", key));
598 is_key = true;
599 continue;
600 }
601
602 if is_key && line.find('}').is_some() {
603 is_key = false;
604 let mut new_len = val_str.len() - 2;
605
606 while !val_str.is_char_boundary(new_len) && new_len > 0 {
607 new_len -= 1;
608 }
609
610 val_str.truncate(new_len);
611
612 txt.push_str(&val_str);
613 txt.push_str("\n\t},\n\n");
614 val_str.clear();
615 continue;
616 }
617
618 if is_key {
619 let fmt_line = line.trim();
620 let var = fmt_line.split('=').next().unwrap_or(fmt_line);
621 let val = fmt_line.split('=').nth(1).unwrap_or("");
622 val_str.push_str(&format!("\t\t\"{}\": \"{}\",\n", val, var));
623 }
624
625 }
626
627 let mut new_len = txt.len() - 3;
628
629 while !txt.is_char_boundary(new_len) && new_len > 0 {
630 new_len -= 1;
631 }
632
633 txt.truncate(new_len);
634 txt.push_str("\n}");
635
636 let full_filename = String::from(&format!("{}.json", filename));
637 let mut file = OpenOptions::new().write(true).truncate(true).create(true).open(full_filename)?;
638 writeln!(file, "{}", txt)?;
639
640 Ok(())
641 }
642
643 pub fn from_toml(&self, toml: &str) -> std::io::Result<()> {
653 let full_toml = String::from(&format!("{}.toml", toml));
654 let file = File::open(full_toml)?;
655 let reader = BufReader::new(&file);
656 let mut txt = String::new();
657 let mut is_one = 0;
658
659 for line in reader.lines() {
660 let line = line?;
661
662 if line.find('[').is_some() && line.find(']').is_some() {
663 let cleaned_line = line.replace(['[', ']'], "");
664 let key = cleaned_line.trim();
665 if is_one > 0 {
666 txt.push_str(&format!("}}\n({}) {{\n", key));
667 } else {
668 txt.push_str(&format!("({}) {{\n", key));
669 }
670 is_one += 1;
671 continue;
672 }
673
674 if !line.is_empty() {
675 let fmt_line = line.replace(['\"', ' '], "");
676 let fmt_line_2 = fmt_line.trim();
677 let var = fmt_line_2.split('=').next().unwrap_or(fmt_line_2);
678 let val = fmt_line_2.split('=').nth(1).unwrap_or("");
679
680 txt.push_str(&format!("\t{}={}\n", var, val));
681 }
682 }
683
684 txt.push_str("}");
685
686 let mut file = OpenOptions::new().write(true).truncate(true).create(true).open(&self.filename)?;
687 writeln!(file, "{}", txt)?;
688
689 Ok(())
690 }
691
692 pub fn from_json(&self, json: &str) -> std::io::Result<()> {
702 let full_json = String::from(&format!("{}.json", json));
703 let file = File::open(full_json)?;
704 let reader = BufReader::new(&file);
705 let mut txt = String::new();
706 let mut is_key = false;
707
708
709 for line in reader.lines() {
710 let line = line?;
711
712 if line.find('\"').is_some() && line.find("{").is_some() && line.find(':').is_some() {
713 let cleaned_line = line.replace(['{', ':', '\"'], "");
714 let key = cleaned_line.trim();
715 txt.push_str(&format!("({}) {{\n", key));
716 is_key = true;
717 continue;
718 }
719
720 if is_key && line.find('}').is_some() {
721 is_key = false;
722 txt.push_str("}\n");
723 continue;
724 }
725
726 if is_key && !line.is_empty() {
727 let cleaned_line = line.replace(['\"', ',', ' '], "");
728 let var_and_val = cleaned_line.trim();
729 let var = var_and_val.split(':').next().unwrap_or(var_and_val);
730 let val = var_and_val.split(':').nth(1).unwrap_or("");
731 txt.push_str(&format!("\t{}={}\n", var, val));
732 }
733 }
734
735 let mut file = OpenOptions::new().write(true).truncate(true).create(true).open(&self.filename)?;
736 writeln!(file, "{}", txt)?;
737
738 Ok(())
739 }
740}