qubit_redact/policy/masking/masking_policy_builder.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//! Mutable construction of the four-level immutable mask table.
9
10use super::MaskPolicy;
11use super::MaskingPolicy;
12use crate::Sensitivity;
13
14/// Mutable construction state for a [`MaskingPolicy`].
15///
16/// # Examples
17///
18/// ```
19/// use qubit_redact::MaskPolicy;
20/// use qubit_redact::MaskingPolicy;
21/// use qubit_redact::Sensitivity;
22///
23/// let mut builder = MaskingPolicy::builder();
24/// builder.secret(MaskPolicy::fixed("[hidden]"));
25/// assert_eq!(builder.build().mask(Sensitivity::Secret, "raw"), "[hidden]");
26/// ```
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct MaskingPolicyBuilder {
29 /// Draft mask for low-sensitivity values.
30 low: MaskPolicy,
31 /// Draft mask for medium-sensitivity values.
32 medium: MaskPolicy,
33 /// Draft mask for high-sensitivity values.
34 high: MaskPolicy,
35 /// Draft mask for secret values.
36 secret: MaskPolicy,
37}
38
39impl MaskingPolicyBuilder {
40 /// Copies every mask from an immutable table into independent draft state.
41 ///
42 /// # Parameters
43 ///
44 /// - `policy`: Immutable mask table to copy.
45 ///
46 /// # Returns
47 ///
48 /// A builder retaining all four mask choices.
49 #[must_use]
50 #[inline(always)]
51 pub(super) fn from_policy(policy: &MaskingPolicy) -> Self {
52 Self {
53 low: policy.for_level(Sensitivity::Low).clone(),
54 medium: policy.for_level(Sensitivity::Medium).clone(),
55 high: policy.for_level(Sensitivity::High).clone(),
56 secret: policy.for_level(Sensitivity::Secret).clone(),
57 }
58 }
59
60 /// Sets the policy for low-sensitivity values.
61 ///
62 /// # Parameters
63 ///
64 /// - `policy`: Replacement masking rule for low sensitivity.
65 ///
66 /// # Returns
67 ///
68 /// This builder with the selected level replaced.
69 #[inline(always)]
70 pub fn low(&mut self, policy: MaskPolicy) -> &mut Self {
71 self.low = policy;
72 self
73 }
74
75 /// Sets the policy for medium-sensitivity values.
76 ///
77 /// # Parameters
78 ///
79 /// - `policy`: Replacement masking rule for medium sensitivity.
80 ///
81 /// # Returns
82 ///
83 /// This builder with the selected level replaced.
84 #[inline(always)]
85 pub fn medium(&mut self, policy: MaskPolicy) -> &mut Self {
86 self.medium = policy;
87 self
88 }
89
90 /// Sets the policy for high-sensitivity values.
91 ///
92 /// # Parameters
93 ///
94 /// - `policy`: Replacement masking rule for high sensitivity.
95 ///
96 /// # Returns
97 ///
98 /// This builder with the selected level replaced.
99 #[inline(always)]
100 pub fn high(&mut self, policy: MaskPolicy) -> &mut Self {
101 self.high = policy;
102 self
103 }
104
105 /// Sets the policy for secret values.
106 ///
107 /// # Parameters
108 ///
109 /// - `policy`: Replacement masking rule for secret sensitivity.
110 ///
111 /// # Returns
112 ///
113 /// This builder with the selected level replaced.
114 #[inline(always)]
115 pub fn secret(&mut self, policy: MaskPolicy) -> &mut Self {
116 self.secret = policy;
117 self
118 }
119
120 /// Builds the immutable masking configuration.
121 ///
122 /// # Returns
123 ///
124 /// The immutable mask table. The enclosing redaction policy builder checks
125 /// that fixed replacements are nonempty before accepting the table.
126 #[must_use]
127 #[inline(always)]
128 pub fn build(self) -> MaskingPolicy {
129 MaskingPolicy::from_parts(self.low, self.medium, self.high, self.secret)
130 }
131
132 /// Replaces one sensitivity policy while rebuilding an existing policy.
133 ///
134 /// # Parameters
135 ///
136 /// - `level`: Sensitivity whose draft mask is replaced.
137 /// - `policy`: Replacement mask for that level.
138 #[inline]
139 pub(crate) fn policy(&mut self, level: Sensitivity, policy: MaskPolicy) {
140 match level {
141 Sensitivity::Low => self.low(policy),
142 Sensitivity::Medium => self.medium(policy),
143 Sensitivity::High => self.high(policy),
144 Sensitivity::Secret => self.secret(policy),
145 };
146 }
147}
148
149impl Default for MaskingPolicyBuilder {
150 /// Creates a builder with the standard masking policies.
151 ///
152 /// # Returns
153 ///
154 /// A builder using the standard low, medium, high, and secret masks.
155 #[inline(always)]
156 fn default() -> Self {
157 Self {
158 low: MaskPolicy::preserve_edges(2, 2, "****", 4),
159 medium: MaskPolicy::preserve_suffix(1, "*******", 1),
160 high: MaskPolicy::fixed("****"),
161 secret: MaskPolicy::fixed("<redacted>"),
162 }
163 }
164}