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}