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 {}