mapfile_parser/
progress_stats.rs

1/* SPDX-FileCopyrightText: © 2023-2025 Decompollaborate */
2/* SPDX-License-Identifier: MIT */
3
4use std::collections::HashMap;
5
6#[cfg(feature = "python_bindings")]
7use pyo3::prelude::*;
8
9#[derive(Debug, Clone)]
10#[cfg_attr(feature = "python_bindings", pyclass(module = "mapfile_parser"))]
11pub struct ProgressStats {
12    pub undecomped_size: usize,
13
14    pub decomped_size: usize,
15}
16
17impl ProgressStats {
18    pub fn new() -> Self {
19        Self {
20            undecomped_size: 0,
21            decomped_size: 0,
22        }
23    }
24
25    pub fn total(&self) -> usize {
26        self.undecomped_size + self.decomped_size
27    }
28
29    pub fn undecomped_percentage(&self) -> f32 {
30        self.undecomped_size as f32 / self.total() as f32 * 100.0
31    }
32
33    pub fn decomped_percentage(&self) -> f32 {
34        self.decomped_size as f32 / self.total() as f32 * 100.0
35    }
36
37    pub fn undecomped_percentage_total(&self, total_stats: &Self) -> f32 {
38        self.undecomped_size as f32 / total_stats.total() as f32 * 100.0
39    }
40
41    pub fn decomped_percentage_total(&self, total_stats: &Self) -> f32 {
42        self.decomped_size as f32 / total_stats.total() as f32 * 100.0
43    }
44
45    pub fn get_as_frogress_entry(&self, name: &str) -> HashMap<String, usize> {
46        let mut categories: HashMap<String, usize> = HashMap::new();
47
48        categories.insert(name.to_string(), self.decomped_size);
49        categories.insert(format!("{}/total", name), self.total());
50
51        categories
52    }
53
54    pub fn get_header_as_str(category_column_size: usize) -> String {
55        format!(
56            "{:<category_column_size$}: {:>12} / {:>8} {:>10}%  ({:>20}%)",
57            "Category",
58            "DecompedSize",
59            "Total",
60            "OfFolder",
61            "OfTotal",
62            category_column_size = category_column_size
63        )
64    }
65
66    pub fn print_header(category_column_size: usize) {
67        println!("{}", Self::get_header_as_str(category_column_size));
68    }
69
70    pub fn get_entry_as_str(
71        &self,
72        category: &str,
73        total_stats: &Self,
74        category_column_size: usize,
75    ) -> String {
76        format!(
77            "{:<category_column_size$}: {:>12} / {:>8} {:>10.4}%  ({:>8.4}% / {:>8.4}%)",
78            category,
79            self.decomped_size,
80            self.total(),
81            self.decomped_percentage(),
82            self.decomped_percentage_total(total_stats),
83            self.total() as f32 / total_stats.total() as f32 * 100.0,
84            category_column_size = category_column_size
85        )
86    }
87
88    pub fn print(&self, category: &str, total_stats: &Self, category_column_size: usize) {
89        println!(
90            "{}",
91            self.get_entry_as_str(category, total_stats, category_column_size)
92        );
93    }
94}
95
96impl Default for ProgressStats {
97    fn default() -> Self {
98        Self::new()
99    }
100}
101
102#[cfg(feature = "python_bindings")]
103#[allow(non_snake_case)]
104pub(crate) mod python_bindings {
105    use pyo3::prelude::*;
106
107    use std::collections::HashMap;
108
109    #[pymethods]
110    impl super::ProgressStats {
111        #[new]
112        fn py_new() -> Self {
113            Self::new()
114        }
115
116        /* Getters and setters */
117
118        #[getter]
119        fn get_undecompedSize(&self) -> PyResult<usize> {
120            Ok(self.undecomped_size)
121        }
122
123        #[setter]
124        fn set_undecompedSize(&mut self, value: usize) -> PyResult<()> {
125            self.undecomped_size = value;
126            Ok(())
127        }
128
129        #[getter]
130        fn get_decompedSize(&self) -> PyResult<usize> {
131            Ok(self.decomped_size)
132        }
133
134        #[setter]
135        fn set_decompedSize(&mut self, value: usize) -> PyResult<()> {
136            self.decomped_size = value;
137            Ok(())
138        }
139
140        #[getter]
141        #[pyo3(name = "total")]
142        fn py_total(&self) -> usize {
143            self.total()
144        }
145
146        /* Methods */
147
148        fn undecompedPercentage(&self) -> f32 {
149            self.undecomped_percentage()
150        }
151
152        fn decompedPercentage(&self) -> f32 {
153            self.decomped_percentage()
154        }
155
156        fn undecompedPercentageTotal(&self, total_stats: &Self) -> f32 {
157            self.undecomped_percentage_total(total_stats)
158        }
159
160        fn decompedPercentageTotal(&self, total_stats: &Self) -> f32 {
161            self.decomped_percentage_total(total_stats)
162        }
163
164        fn getAsFrogressEntry(&self, name: &str) -> HashMap<String, usize> {
165            self.get_as_frogress_entry(name)
166        }
167
168        #[staticmethod]
169        #[pyo3(signature=(category_column_size=28))]
170        fn getHeaderAsStr(category_column_size: usize) -> String {
171            Self::get_header_as_str(category_column_size)
172        }
173
174        #[staticmethod]
175        #[pyo3(signature=(category_column_size=28))]
176        fn printHeader(category_column_size: usize) {
177            Self::print_header(category_column_size)
178        }
179
180        #[pyo3(signature=(category, total_stats, category_column_size=28))]
181        fn getEntryAsStr(
182            &self,
183            category: &str,
184            total_stats: &Self,
185            category_column_size: usize,
186        ) -> String {
187            self.get_entry_as_str(category, total_stats, category_column_size)
188        }
189
190        #[pyo3(name = "print")]
191        #[pyo3(signature=(category, total_stats, category_column_size=28))]
192        fn py_print(&self, category: &str, total_stats: &Self, category_column_size: usize) {
193            self.print(category, total_stats, category_column_size)
194        }
195    }
196}