Skip to content

Commit 480c194

Browse files
committed
v3, added report system and cleaning the code
1 parent 44c208d commit 480c194

File tree

6 files changed

+195
-37
lines changed

6 files changed

+195
-37
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "yet-another-disk-mapper"
2+
name = "yadm"
33
version = "0.1.0"
44
edition = "2021"
55

readme.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,78 @@
11
# Yet Another Disk Mapper (YADM)
2-
YADM is a little Disk Mapper for some future projects.
2+
3+
**YADM** is a lightweight disk mapping tool designed for small-scale projects.
4+
It allows you to serialize the structure of a file system directory into compact and optimized formats for fast storage and access.
5+
6+
---
7+
8+
## 🚀 Features
9+
10+
- Generates lightweight and ultra-optimized mapping files.
11+
- Provides serializers for Rust to handle `.msgpack.tar.gz` files.
12+
13+
---
14+
15+
## ⚙️ How It Works
16+
17+
Running a command like `./yadm.exe serialize "C://"` will perform the following steps:
18+
19+
1. Traverse the specified directory and collect all file and folder metadata.
20+
2. Convert the resulting data structure into a [MessagePack](https://msgpack.org/) object.
21+
3. Compress the MessagePack file using `tar.gz`.
22+
4. Output the final mapping as `map.msgpack.tar.gz`.
23+
24+
In my personal configuration :
25+
- SSD NVMe
26+
- 471,45 Go on 500,00 Go used
27+
- Output result :
28+
```
29+
1. Scanning folders at: C://
30+
Scan Time: 195.4473487s
31+
Elements found: 2065488
32+
2. Parsing to hashmap...
33+
3. Encoding + writing MessagePack...
34+
35+
--- Résultats ---
36+
Compression Time: 5.5725601s
37+
Average compression time per file: 2697 ns
38+
Compressed file size: 358444787 octets
39+
Compressed file size: 350043.74 Ko
40+
Compressed file size: 341.84 Mo
41+
Average compressed size per file: 173 octets
42+
```
43+
---
44+
45+
## 🧰 Commands
46+
47+
There are two main commands:
48+
49+
- `yadm serialize "path" --use-tar-gz=true`
50+
→ Maps a directory and outputs a compressed `.msgpack.tar.gz` file.
51+
52+
- `yadm serialize "path" --use-tar-gz=false`
53+
→ Outputs a raw `.msgpack` file (uncompressed).
54+
55+
- `yadm parse "map.msgpack.tar.gz"`
56+
→ Parses the mapping and loads it into memory as a `Vec<HashMap<String, String>>`.
57+
58+
---
59+
60+
## 🦀 Usage in Rust
61+
62+
You can integrate YADM directly in your Rust project like this:
63+
64+
```rust
65+
use yadm::{serialize, parse};
66+
use std::collections::HashMap;
67+
68+
fn main() {
69+
// Serialize a directory
70+
serialize("C://", true);
71+
72+
// Parse the resulting file
73+
let map: Vec<HashMap<String, String>> = parse("map.msgpack.tar.gz");
74+
75+
// You can now use `map` in your application
76+
}
77+
```
78+
> ⚠️ Make sure to handle Result and error types appropriately in real applications.

src/main.rs

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,13 @@ use std::env;
22
use std::fs::File;
33
use std::io::Write;
44
use std::path::{Path, PathBuf};
5-
use std::time::Instant;
5+
use std::time::{Duration, Instant};
66
use std::collections::HashMap;
77
use rmp_serde::encode;
88
use walkdir::WalkDir;
99

10-
fn format_file_size(size: u64, unit: &str) -> String {
11-
match unit {
12-
"o" => format!("{} octets", size),
13-
"Ko" => format!("{:.2} Ko", size as f64 / 1024.0),
14-
"Mo" => format!("{:.2} Mo", size as f64 / (1024.0 * 1024.0)),
15-
"Go" => format!("{:.2} Go", size as f64 / (1024.0 * 1024.0 * 1024.0)),
16-
_ => format!("{} octets", size),
17-
}
18-
}
10+
mod yadm;
11+
use yadm::report::report::Report;
1912

2013
fn scan_dir(path: &Path) -> Vec<PathBuf> {
2114
WalkDir::new(path)
@@ -27,8 +20,8 @@ fn scan_dir(path: &Path) -> Vec<PathBuf> {
2720
}
2821

2922
fn parsing_to_hashmap(entries: &[PathBuf]) -> Vec<HashMap<String, String>> {
30-
entries.iter().map(|entry| {
31-
let mut hashmap = HashMap::new();
23+
entries.iter().map(|entry: &PathBuf| {
24+
let mut hashmap: HashMap<String, String> = HashMap::new();
3225
hashmap.insert("name".to_string(), entry.file_name().unwrap_or_default().to_string_lossy().into_owned());
3326
hashmap.insert("ext".to_string(), entry.extension().unwrap_or_default().to_string_lossy().into_owned());
3427
hashmap.insert("path".to_string(), entry.to_string_lossy().into_owned());
@@ -44,34 +37,56 @@ fn main() {
4437
std::process::exit(1);
4538
}
4639

47-
let target_dir = &args[1];
40+
let target_dir: &String = &args[1];
41+
4842
println!("1. Scanning folders at: {}", target_dir);
43+
let scan_start: Instant = Instant::now();
44+
let paths: Vec<PathBuf> = scan_dir(Path::new(target_dir));
45+
let scan_duration: Duration = scan_start.elapsed();
4946

50-
let start_time = Instant::now();
51-
let paths = scan_dir(Path::new(target_dir));
52-
let end_time = start_time.elapsed();
47+
let total_files: u64 =
48+
if paths.is_empty() {
49+
eprintln!("No files found. Exiting.");
50+
return;
51+
} else {
52+
let count = paths.len() as u64;
53+
println!("Found {} files", count);
54+
count
55+
};
5356

54-
println!("Time taken: {:?}", end_time);
55-
println!("Elements found: {:?}", paths.len());
5657

57-
if !paths.is_empty() {
58-
let medium_time_per_element = end_time.as_nanos() / paths.len() as u128;
59-
println!("Medium time by element: {:?} ns", medium_time_per_element);
60-
} else {
61-
println!("No elements found, cannot calculate medium time by element.");
62-
}
58+
println!("2. Parsing to hashmap...");
59+
let hashmap_parsing_start: Instant = Instant::now();
60+
let hashmap: Vec<HashMap<String, String>> = parsing_to_hashmap(&paths);
61+
let hashmap_parsing_duration: Duration = hashmap_parsing_start.elapsed();
62+
6363

64-
let hashmap = parsing_to_hashmap(&paths);
65-
let encoded = encode::to_vec(&hashmap).unwrap();
64+
println!("3. Encoding + writing MessagePack...");
65+
let msgpack_parsing_start = Instant::now();
6666

67-
let mut file = File::create("output.msgpack").expect("Impossible de créer le fichier");
67+
let encoded: Vec<u8> = encode::to_vec(&hashmap).unwrap();
68+
let mut file: File = File::create("output.msgpack").expect("Impossible de créer le fichier");
6869
file.write_all(&encoded).expect("Impossible d'écrire dans le fichier");
6970

70-
let metadata = file.metadata().expect("Impossible d'obtenir les métadonnées du fichier");
71-
let file_size = metadata.len();
71+
let msgpack_parsing_duration: Duration = msgpack_parsing_start.elapsed();
7272

73-
println!("Taille du fichier : {}", format_file_size(file_size, "o"));
74-
println!("Taille du fichier : {}", format_file_size(file_size, "Ko"));
75-
println!("Taille du fichier : {}", format_file_size(file_size, "Mo"));
76-
println!("Taille du fichier : {}", format_file_size(file_size, "Go"));
77-
}
73+
let metadata: std::fs::Metadata = file.metadata().expect("Impossible d'obtenir les métadonnées du fichier");
74+
let file_size: u64 = metadata.len();
75+
76+
let report: Report = Report {
77+
target: args[0].clone(),
78+
scan_start_at: scan_start,
79+
scan_duration: scan_duration,
80+
elements_found: file_size,
81+
hashmap_parsing_start_at: hashmap_parsing_start,
82+
hashmap_parsing_duration: hashmap_parsing_duration,
83+
msgpack_parsing_start_at: msgpack_parsing_start,
84+
msgpack_parsing_duration: msgpack_parsing_duration,
85+
output_file_size: file_size,
86+
full_duration: scan_duration+hashmap_parsing_duration+msgpack_parsing_duration,
87+
average_duration_by_file: file_size.checked_div(scan_duration.as_secs()+hashmap_parsing_duration.as_secs()+msgpack_parsing_duration.as_secs()).unwrap_or(0),
88+
average_size_by_file: file_size.checked_div(total_files).unwrap_or(0),
89+
};
90+
91+
println!("{}", report)
92+
}

src/yadm/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod report;

src/yadm/report.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use std::fmt;
2+
use std::time::{Duration, Instant};
3+
4+
pub mod report {
5+
use super::*;
6+
7+
pub struct Report {
8+
pub target: String,
9+
pub scan_start_at: Instant,
10+
pub scan_duration: Duration,
11+
pub elements_found: u64,
12+
13+
pub hashmap_parsing_start_at: Instant,
14+
pub hashmap_parsing_duration: Duration,
15+
16+
pub msgpack_parsing_start_at: Instant,
17+
pub msgpack_parsing_duration: Duration,
18+
19+
pub output_file_size: u64,
20+
pub full_duration: Duration,
21+
pub average_duration_by_file: u64,
22+
pub average_size_by_file: u64,
23+
}
24+
25+
impl fmt::Display for Report {
26+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27+
write!(f, "Scan of {} found {} elements in {:?}",
28+
self.target,
29+
self.elements_found,
30+
self.full_duration
31+
)?;
32+
33+
write!(
34+
f, "
35+
=== YADM report ===
36+
Target : {}
37+
Scan duration : {:.2}s
38+
Elements found : {}
39+
Hashmap parsing duration : {:.2}s
40+
MsgPack parsing duration : {:.2}s
41+
-----
42+
Full duration : {:.2}s
43+
Average duration by file : {:.2}s
44+
Average size by file : {} o
45+
Output file size : {} o
46+
Output file size : {:.2} Ko
47+
Output file size : {:.2} Mo
48+
Output file size : {:.2} Go
49+
===================
50+
",
51+
self.target,
52+
self.scan_duration.as_secs_f64(),
53+
self.elements_found,
54+
self.hashmap_parsing_duration.as_secs_f64(),
55+
self.msgpack_parsing_duration.as_secs_f64(),
56+
self.full_duration.as_secs_f64(),
57+
self.average_duration_by_file,
58+
self.average_size_by_file,
59+
self.output_file_size,
60+
self.output_file_size as f64 / 1024.0,
61+
self.output_file_size as f64 / (1024.0 * 1024.0),
62+
self.output_file_size as f64 / (1024.0 * 1024.0 * 1024.0),
63+
)
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)