qubit_redact/policy/diagnostic_budget.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//! Hard input and output limits for redacted diagnostics.
9// qubit-style: allow type-file-name
10
11use super::DiagnosticBudgetError;
12
13/// Bounds both inspected diagnostic bytes and produced log-safe bytes.
14#[must_use]
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct InputOutputLimit {
17 /// Maximum number of source bytes a diagnostic redactor may inspect.
18 max_input_bytes: usize,
19 /// Maximum number of bytes in the final log-safe rendering.
20 max_output_bytes: usize,
21}
22
23impl InputOutputLimit {
24 /// Smallest output limit that can contain the diagnostic-limit marker.
25 pub const MIN_OUTPUT_BYTES: usize =
26 "<redacted: diagnostic limit exceeded>".len();
27
28 /// Creates checked hard limits for diagnostic processing.
29 ///
30 /// # Parameters
31 ///
32 /// * `max_input_bytes` - Maximum source bytes one diagnostic may inspect.
33 /// * `max_output_bytes` - Maximum bytes in the final log-safe rendering.
34 ///
35 /// # Returns
36 ///
37 /// A validated diagnostic budget.
38 ///
39 /// # Errors
40 ///
41 /// Returns [`DiagnosticBudgetError::ZeroInput`] when `max_input_bytes` is
42 /// zero, or [`DiagnosticBudgetError::OutputTooSmall`] when the output limit
43 /// cannot contain the diagnostic-limit marker.
44 #[inline]
45 pub const fn new(
46 max_input_bytes: usize,
47 max_output_bytes: usize,
48 ) -> Result<Self, DiagnosticBudgetError> {
49 if max_input_bytes == 0 {
50 return Err(DiagnosticBudgetError::ZeroInput);
51 }
52 if max_output_bytes < Self::MIN_OUTPUT_BYTES {
53 return Err(DiagnosticBudgetError::OutputTooSmall {
54 minimum: Self::MIN_OUTPUT_BYTES,
55 actual: max_output_bytes,
56 });
57 }
58 Ok(Self {
59 max_input_bytes,
60 max_output_bytes,
61 })
62 }
63
64 /// Returns the maximum number of source bytes a diagnostic may inspect.
65 ///
66 /// # Returns
67 ///
68 /// The configured source-byte limit.
69 #[must_use]
70 #[inline(always)]
71 pub const fn max_input_bytes(self) -> usize {
72 self.max_input_bytes
73 }
74
75 /// Returns the maximum final log-safe diagnostic size.
76 ///
77 /// # Returns
78 ///
79 /// The configured output-byte limit.
80 #[must_use]
81 #[inline(always)]
82 pub const fn max_output_bytes(self) -> usize {
83 self.max_output_bytes
84 }
85}
86
87impl Default for InputOutputLimit {
88 /// Returns conservative 16 KiB input and 64 KiB output limits.
89 ///
90 /// # Returns
91 ///
92 /// A diagnostic budget with the documented conservative limits.
93 #[inline(always)]
94 fn default() -> Self {
95 Self {
96 max_input_bytes: 16 * 1024,
97 max_output_bytes: 64 * 1024,
98 }
99 }
100}