Skip to main content

qubit_redact/facade/
redaction_reason.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Reasons why a safe representation is degraded.
9
10/// Reason why a policy-transformed representation is degraded.
11///
12/// # Examples
13///
14/// ```
15/// use qubit_redact::{RedactionPolicy, RedactionReason, Redactor};
16///
17/// let policy = RedactionPolicy::builder().limits(|limits| {
18///     limits.max_input_bytes(0);
19/// })?.build()?;
20/// let output = Redactor::new(policy).redact_field("id", "42");
21/// assert!(output.summary().reasons().contains(RedactionReason::InputLimitReached));
22/// # Ok::<(), qubit_redact::PolicyError>(())
23/// ```
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
25#[non_exhaustive]
26pub enum RedactionReason {
27    /// Input admission rejected bytes beyond the configured input allowance.
28    InputLimitReached,
29    /// The shared transaction output reached its configured byte limit.
30    OutputLimitReached,
31    /// Structural traversal reached a configured limit.
32    TraversalLimitReached,
33    /// Maximum traversal depth was reached.
34    DepthLimitReached,
35    /// Source data was already truncated at its ingress boundary.
36    SourceTruncated,
37    /// Source data was not valid JSON.
38    InvalidJson,
39    /// Source data was not a valid URI.
40    InvalidUri,
41    /// Source content type was invalid.
42    InvalidContentType,
43    /// Source content type is unsupported.
44    UnsupportedContentType,
45    /// Source data was not a valid URL-encoded form.
46    InvalidForm,
47    /// Source data was not a valid multipart body.
48    InvalidMultipart,
49    /// A display formatter failed before producing a complete scalar value.
50    FormattingFailed,
51}
52
53impl RedactionReason {
54    /// Returns the stable bit assigned to this reason in a reason set.
55    ///
56    /// # Returns
57    ///
58    /// Exactly one bit identifying this reason in the internal reason set.
59    #[must_use]
60    pub(super) const fn bit(self) -> u64 {
61        match self {
62            Self::InputLimitReached => 1 << 0,
63            Self::OutputLimitReached => 1 << 1,
64            Self::TraversalLimitReached => 1 << 2,
65            Self::DepthLimitReached => 1 << 3,
66            Self::SourceTruncated => 1 << 4,
67            Self::InvalidJson => 1 << 5,
68            Self::InvalidUri => 1 << 6,
69            Self::InvalidContentType => 1 << 7,
70            Self::UnsupportedContentType => 1 << 8,
71            Self::InvalidForm => 1 << 9,
72            Self::InvalidMultipart => 1 << 10,
73            Self::FormattingFailed => 1 << 11,
74        }
75    }
76}