qubit_redact/text/log_output_limit.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//! Validated byte limits for bounded log output.
9
10use crate::{
11 DiagnosticBudget,
12 LogOutputLimitError,
13};
14
15/// Marker appended when bounded log output is truncated.
16pub(crate) const TRUNCATION_MARKER: &str = "<truncated>";
17
18/// Maximum byte count for one bounded redacted log representation.
19#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
20#[must_use = "use the validated limit to bound redacted display output"]
21pub struct LogOutputLimit {
22 /// Maximum rendered bytes, including any truncation marker.
23 max_bytes: usize,
24}
25
26impl LogOutputLimit {
27 /// Smallest valid limit, equal to the byte length of the truncation marker.
28 pub const MINIMUM: usize = TRUNCATION_MARKER.len();
29
30 /// Validates a maximum output byte count.
31 ///
32 /// # Parameters
33 ///
34 /// * `max_bytes` - Maximum rendered bytes, including any truncation marker.
35 ///
36 /// # Returns
37 ///
38 /// A validated output limit.
39 ///
40 /// # Errors
41 ///
42 /// Returns [`LogOutputLimitError`] when `max_bytes` cannot contain the
43 /// complete truncation marker.
44 #[inline]
45 pub const fn new(max_bytes: usize) -> Result<Self, LogOutputLimitError> {
46 if max_bytes < Self::MINIMUM {
47 Err(LogOutputLimitError::new(max_bytes))
48 } else {
49 Ok(Self { max_bytes })
50 }
51 }
52
53 /// Returns the maximum rendered byte count.
54 ///
55 /// # Returns
56 ///
57 /// The byte budget, including any truncation marker.
58 #[inline(always)]
59 pub const fn max_bytes(self) -> usize {
60 self.max_bytes
61 }
62}
63
64impl From<DiagnosticBudget> for LogOutputLimit {
65 /// Converts a diagnostic budget into its compatible log-output limit.
66 ///
67 /// [`DiagnosticBudget`] guarantees an output bound large enough for every
68 /// [`LogOutputLimit`].
69 ///
70 /// # Parameters
71 ///
72 /// * `budget` - Diagnostic budget whose output limit is converted.
73 ///
74 /// # Returns
75 ///
76 /// A compatible validated log-output limit.
77 #[inline(always)]
78 fn from(budget: DiagnosticBudget) -> Self {
79 Self {
80 max_bytes: budget.max_output_bytes(),
81 }
82 }
83}