idar/
models.rs

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        // Serialize and then deserialize the report
95        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}