1use image_hasher::ImageHash;
2use serde::{Deserialize, Serialize};
3use std::fmt::{self};
4use std::path::PathBuf;
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
7pub struct ImageInfo {
8 pub path: PathBuf,
9 #[serde(
10 serialize_with = "crate::serialization::hash_to_base64",
11 deserialize_with = "crate::serialization::hash_from_base64"
12 )]
13 pub hash: ImageHash,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
17pub struct DuplicatesGroup {
18 pub items: Vec<ImageInfo>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
22pub struct DeduplicationMetadata {
23 pub directory_path: PathBuf,
24 pub threshold: u32,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
28pub struct DeduplicationReport {
29 pub metadata: DeduplicationMetadata,
30 pub groups: Vec<DuplicatesGroup>,
31 pub total_duplicates: usize,
32}
33
34impl DeduplicationReport {
35 pub fn new(
36 directory_path: PathBuf,
37 groups: Vec<DuplicatesGroup>,
38 duplicate_threshold: u32,
39 ) -> Self {
40 let metadata = DeduplicationMetadata {
41 directory_path,
42 threshold: duplicate_threshold,
43 };
44
45 let total_duplicates: usize =
46 groups.iter().map(|g| g.items.len()).sum::<usize>() - groups.len();
47
48 DeduplicationReport {
49 metadata,
50 groups,
51 total_duplicates,
52 }
53 }
54}
55
56impl fmt::Display for DeduplicationReport {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 writeln!(f, "Deduplication Report:")?;
59 writeln!(
60 f,
61 "Directory path: {}",
62 self.metadata.directory_path.display()
63 )?;
64 writeln!(f, "Similarity threshold: {}", self.metadata.threshold)?;
65 writeln!(f, "Number of duplicate groups: {}", self.groups.len())?;
66 writeln!(f, "Total number of duplicates: {}", self.total_duplicates)?;
67 Ok(())
68 }
69}
70
71#[allow(unused_imports)]
72mod test {
73 use super::*;
74
75 #[test]
76 fn test_serialize_deserialize_dedupe_report() {
77 let hash: ImageHash = ImageHash::from_base64("DAIDBwMHAf8").unwrap();
78 let image = ImageInfo {
79 path: PathBuf::from("/path/to/image.jpg"),
80 hash,
81 };
82
83 let report = DeduplicationReport {
84 metadata: DeduplicationMetadata {
85 directory_path: PathBuf::from("/path/to/directory"),
86 threshold: 10,
87 },
88 groups: vec![DuplicatesGroup {
89 items: vec![image.clone()],
90 }],
91 total_duplicates: 1,
92 };
93
94 let serialized = serde_json::to_string(&report).unwrap();
96 let deserialized: DeduplicationReport = serde_json::from_str(&serialized).unwrap();
97 assert_eq!(report, deserialized);
98 }
99}