parallel_disk_usage/reporter/
progress_report.rs

1use crate::{size, status_board::GLOBAL_STATUS_BOARD};
2use derive_setters::Setters;
3use std::fmt::Write;
4
5/// Scan progress.
6#[derive(Debug, Default, Setters, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
7#[setters(prefix = "with_")]
8pub struct ProgressReport<Size: size::Size> {
9    /// Number of scanned items.
10    pub items: u64,
11    /// Total size of scanned items.
12    pub total: Size,
13    /// Number of occurred errors.
14    pub errors: u64,
15    /// Total number of detected hardlinks.
16    pub linked: u64,
17    /// Total size of detected hardlinks.
18    pub shared: Size,
19}
20
21impl<Size: size::Size + Into<u64>> ProgressReport<Size> {
22    /// Maximum length by which the progress text may extend.
23    ///
24    /// This constant is used as capacity in [`Self::TEXT`] to prevent
25    /// performance penalty from string resizing.
26    ///
27    /// The value of this constant is made correct by a unit test.
28    const TEXT_MAX_LEN: usize = 145;
29
30    /// Create a text to be used in [`Self::TEXT`].
31    fn text(self) -> String {
32        let ProgressReport {
33            items,
34            total,
35            errors,
36            linked,
37            shared,
38        } = self;
39        let mut text = String::with_capacity(Self::TEXT_MAX_LEN);
40        let total: u64 = total.into();
41        write!(text, "\r(scanned {items}, total {total}").unwrap();
42        if linked != 0 {
43            write!(text, ", linked {linked}").unwrap();
44        }
45        let shared: u64 = shared.into();
46        if shared != 0 {
47            write!(text, ", shared {shared}").unwrap();
48        }
49        if errors != 0 {
50            write!(text, ", erred {errors}").unwrap();
51        }
52        text.push(')');
53        text
54    }
55
56    /// Print progress to stderr.
57    pub const TEXT: fn(Self) = |report| {
58        GLOBAL_STATUS_BOARD.temporary_message(&report.text());
59    };
60}
61
62#[test]
63fn text_max_len() {
64    use crate::size::Bytes;
65    let correct_value = ProgressReport::<Bytes> {
66        items: u64::MAX,
67        total: u64::MAX.into(),
68        errors: u64::MAX,
69        linked: u64::MAX,
70        shared: u64::MAX.into(),
71    }
72    .text()
73    .len();
74    assert_eq!(ProgressReport::<Bytes>::TEXT_MAX_LEN, correct_value);
75}