Skip to main content

qubit_redact/domain/internal/
redact_value_serialize.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//! Generated structured serialization capability and containers.
9
10use serde::Serializer;
11use serde::ser::SerializeSeq;
12use serde::ser::SerializeTuple;
13
14use super::redact_serialize::RedactSerialize;
15use super::redact_serialize_scope::admit_collection_items;
16use super::redact_serialize_scope::serialize_structured;
17use super::redacted_serialize_ref::RedactedSerializeRef;
18
19impl<T: RedactSerialize> RedactSerialize for Option<T> {
20    /// Serializes contained redacted values through the active policy scope.
21    ///
22    /// # Errors
23    ///
24    /// Propagates child serialization and shared-budget failures.
25    fn serialize_redacted<S>(&self, serializer: S, policy: &crate::RedactionPolicy) -> Result<S::Ok, S::Error>
26    where
27        S: Serializer,
28    {
29        match self {
30            Some(value) => value.serialize_redacted(serializer, policy),
31            None => serializer.serialize_none(),
32        }
33    }
34}
35
36impl<T: RedactSerialize> RedactSerialize for Vec<T> {
37    /// Serializes contained redacted values through the active policy scope.
38    ///
39    /// # Errors
40    ///
41    /// Propagates child serialization and shared-budget failures.
42    fn serialize_redacted<S>(&self, serializer: S, policy: &crate::RedactionPolicy) -> Result<S::Ok, S::Error>
43    where
44        S: Serializer,
45    {
46        serialize_structured(serializer, policy, |serializer| {
47            if !admit_collection_items(self.len()) {
48                return super::redact_serialize_scope::serialize_payload(
49                    serializer,
50                    policy.masking().mask_opaque(crate::Sensitivity::Secret),
51                );
52            }
53            let mut sequence = serializer.serialize_seq(Some(self.len()))?;
54            for value in self {
55                sequence.serialize_element(&RedactedSerializeRef::new(value, policy))?;
56            }
57            sequence.end()
58        })
59    }
60}
61
62impl<T: RedactSerialize, const N: usize> RedactSerialize for [T; N] {
63    /// Serializes contained redacted values through the active policy scope.
64    ///
65    /// # Errors
66    ///
67    /// Propagates child serialization and shared-budget failures.
68    fn serialize_redacted<S>(&self, serializer: S, policy: &crate::RedactionPolicy) -> Result<S::Ok, S::Error>
69    where
70        S: Serializer,
71    {
72        serialize_structured(serializer, policy, |serializer| {
73            if !admit_collection_items(N) {
74                return super::redact_serialize_scope::serialize_payload(
75                    serializer,
76                    policy.masking().mask_opaque(crate::Sensitivity::Secret),
77                );
78            }
79            let mut sequence = serializer.serialize_seq(Some(N))?;
80            for value in self {
81                sequence.serialize_element(&RedactedSerializeRef::new(value, policy))?;
82            }
83            sequence.end()
84        })
85    }
86}
87
88/// Generates tuple projections that prepay their arity before visiting
89/// children.
90macro_rules! tuple_redact_serialize {
91    ($count:expr; $($name:ident => $index:tt),+) => {
92        impl<$($name: RedactSerialize),+> RedactSerialize for ($($name,)+) {
93            /// Serializes contained redacted values through the active policy scope.
94            ///
95            /// # Errors
96            ///
97            /// Propagates child serialization and shared-budget failures.
98            fn serialize_redacted<S>(&self, serializer: S, policy: &crate::RedactionPolicy) -> Result<S::Ok, S::Error>
99            where
100                S: Serializer,
101            {
102                serialize_structured(serializer, policy, |serializer| {
103                if !admit_collection_items($count) {
104                    return super::redact_serialize_scope::serialize_payload(serializer,
105                        policy
106                            .masking()
107                            .mask_opaque(crate::Sensitivity::Secret)
108                            .as_ref(),
109                    );
110                }
111                let mut tuple = serializer.serialize_tuple($count)?;
112                $(tuple.serialize_element(&RedactedSerializeRef::new(&self.$index, policy))?;)+
113                tuple.end()
114                })
115            }
116        }
117    };
118}
119
120tuple_redact_serialize!(1; A => 0);
121tuple_redact_serialize!(2; A => 0, B => 1);
122tuple_redact_serialize!(3; A => 0, B => 1, C => 2);
123tuple_redact_serialize!(4; A => 0, B => 1, C => 2, D => 3);
124tuple_redact_serialize!(5; A => 0, B => 1, C => 2, D => 3, E => 4);
125tuple_redact_serialize!(6; A => 0, B => 1, C => 2, D => 3, E => 4, F => 5);
126tuple_redact_serialize!(7; A => 0, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6);
127tuple_redact_serialize!(8; A => 0, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6, H => 7);
128tuple_redact_serialize!(9; A => 0, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6, H => 7, I => 8);
129tuple_redact_serialize!(10; A => 0, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6, H => 7, I => 8, J => 9);
130tuple_redact_serialize!(11; A => 0, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6, H => 7, I => 8, J => 9, K => 10);
131tuple_redact_serialize!(12; A => 0, B => 1, C => 2, D => 3, E => 4, F => 5, G => 6, H => 7, I => 8, J => 9, K => 10, L => 11);