Skip to main content

qubit_redact/facade/
redaction_inspection_error.rs

1// =============================================================================
2//    Copyright (c) 2025 - 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Fail-closed error returned when inspection cannot classify complete input.
9
10use std::error::Error;
11use std::fmt;
12
13use super::RedactionReasons;
14use super::RedactionUsage;
15
16/// An inconclusive redaction inspection.
17///
18/// Callers must treat this error as potentially sensitive. The error exposes
19/// only bounded accounting and machine-readable reasons; it never retains the
20/// original input or a partial sensitivity result.
21///
22/// # Examples
23///
24/// ```
25/// use qubit_redact::RedactionPolicy;
26/// use qubit_redact::RedactionReason;
27/// use qubit_redact::Redactor;
28///
29/// let policy = RedactionPolicy::builder().limits(|limits| {
30///     limits.max_input_bytes(0);
31/// })?.build()?;
32/// let error = Redactor::new(policy).inspect_field("id", "42").expect_err("no input allowed");
33/// assert!(error.reasons().contains(RedactionReason::InputLimitReached));
34/// # Ok::<(), qubit_redact::PolicyError>(())
35/// ```
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37#[must_use]
38pub struct RedactionInspectionError {
39    /// Causes that prevented a conclusive classification.
40    reasons: RedactionReasons,
41    /// Resources consumed before inspection stopped.
42    usage: RedactionUsage,
43}
44
45impl RedactionInspectionError {
46    /// Creates an error from runtime-owned failure metadata.
47    ///
48    /// # Parameters
49    ///
50    /// - `reasons`: Causes preventing complete classification.
51    /// - `usage`: Resources consumed before inspection stopped.
52    ///
53    /// # Returns
54    ///
55    /// A value-free error retaining reasons and usage, without partial
56    /// sensitivity.
57    #[inline(always)]
58    pub(crate) const fn new(reasons: RedactionReasons, usage: RedactionUsage) -> Self {
59        Self { reasons, usage }
60    }
61
62    /// Returns the machine-readable causes of incomplete inspection.
63    ///
64    /// # Returns
65    ///
66    /// The accumulated causes of inconclusive inspection.
67    #[must_use]
68    #[inline(always)]
69    pub const fn reasons(&self) -> RedactionReasons {
70        self.reasons
71    }
72
73    /// Returns resources consumed before the inspection became inconclusive.
74    ///
75    /// # Returns
76    ///
77    /// Resources consumed before complete classification became unavailable.
78    #[must_use]
79    #[inline(always)]
80    pub const fn usage(&self) -> RedactionUsage {
81        self.usage
82    }
83}
84
85impl fmt::Display for RedactionInspectionError {
86    /// Writes a safe diagnostic that never includes inspected input.
87    ///
88    /// # Parameters
89    ///
90    /// - `formatter`: Destination receiving a value-free diagnostic.
91    ///
92    /// # Returns
93    ///
94    /// Success after writing the inconclusive-inspection diagnostic.
95    ///
96    /// # Errors
97    ///
98    /// Propagates a destination formatting error.
99    #[inline(always)]
100    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
101        formatter.write_str("redaction inspection was inconclusive")
102    }
103}
104
105impl Error for RedactionInspectionError {}