Skip to main content

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}