dry4rust/cli/checking/check_thresholds.rs
1// Copyright (c) 2026 Matjaz Domen Pecan
2// Copyright 2026 Umberto Gotti <umberto.gotti@umbertogotti.dev>
3// Licensed under the MIT License
4// SPDX-License-Identifier: MIT
5
6use crate::error::Result;
7use crate::threshold::Threshold;
8
9/// The four ceilings `check` measures a result against.
10///
11/// Every field is optional and an absent one is not a ceiling of zero -- it
12/// means the caller did not ask about that dimension, so nothing can breach
13/// it. `Default` therefore describes a `check` that reports and never fails,
14/// which is what running `check` with no flags does.
15#[derive(Debug, Clone, Default)]
16pub struct CheckThresholds {
17 /// Most exact-duplicate groups allowed.
18 pub max_exact: Option<usize>,
19 /// Most near-duplicate groups allowed.
20 pub max_near: Option<usize>,
21 /// Largest share of lines allowed to be exact duplicates.
22 pub max_exact_percent: Option<Threshold>,
23 /// Largest share of lines allowed to be near duplicates.
24 pub max_near_percent: Option<Threshold>,
25}
26
27impl CheckThresholds {
28 /// Build the ceilings from what the command line asked for.
29 ///
30 /// # Errors
31 ///
32 /// Returns [`crate::error::Error::InvalidConfig`] naming the flag whose
33 /// value is not a share of a hundred.
34 pub fn new(
35 max_exact: Option<usize>,
36 max_near: Option<usize>,
37 max_exact_percent: Option<f64>,
38 max_near_percent: Option<f64>,
39 ) -> Result<Self> {
40 Ok(Self {
41 max_exact,
42 max_near,
43 max_exact_percent: max_exact_percent
44 .map(|value| Threshold::percent("--max-exact-percent", value))
45 .transpose()?,
46 max_near_percent: max_near_percent
47 .map(|value| Threshold::percent("--max-near-percent", value))
48 .transpose()?,
49 })
50 }
51
52 /// Whether any ceiling was set at all.
53 ///
54 /// A `check` with none set can still report, and still exits zero however
55 /// much duplication it finds.
56 #[must_use]
57 pub const fn is_unbounded(&self) -> bool {
58 self.max_exact.is_none()
59 && self.max_near.is_none()
60 && self.max_exact_percent.is_none()
61 && self.max_near_percent.is_none()
62 }
63}