Skip to main content

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}