Skip to main content

qubit_value/value/
redaction.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//! Policy-aware redaction for structured [`super::Value`] instances.
9
10use qubit_redact::Redact;
11use qubit_redact::RedactionWriter;
12
13use super::Value;
14use super::ValueRepr;
15use super::internal::RedactedStringMap;
16use crate::MultiValues;
17use crate::MultiValuesRef;
18use crate::NamedMultiValues;
19use crate::NamedValue;
20use crate::ValueContainer;
21
22impl Redact for Value {
23    /// Writes one value through the shared structured writer.
24    fn write_redacted(&self, writer: &mut RedactionWriter<'_>) {
25        match &self.repr {
26            ValueRepr::StringMap(values) => {
27                writer.record("Value", |fields| {
28                    fields.map("StringMap", values);
29                });
30            }
31            #[cfg(feature = "json")]
32            ValueRepr::Json(value) => {
33                writer.record("Value", |fields| {
34                    fields.json_value("Json", value);
35                });
36            }
37            _ => {
38                writer.unredacted(self);
39            }
40        }
41    }
42}
43
44impl Redact for MultiValues {
45    /// Writes a typed collection through the shared structured writer.
46    fn write_redacted(&self, writer: &mut RedactionWriter<'_>) {
47        match self.view() {
48            MultiValuesRef::StringMap(values) => {
49                writer.sequence(|items| {
50                    items.for_each(values, |items, values| {
51                        items.nested_item(&RedactedStringMap { values });
52                    });
53                });
54            }
55            MultiValuesRef::String(values) => {
56                writer.sequence(|items| {
57                    items.for_each(values, |items, value| {
58                        items.unredacted_item(|| value);
59                    });
60                });
61            }
62            #[cfg(feature = "json")]
63            MultiValuesRef::Json(values) => {
64                writer.sequence(|items| {
65                    items.for_each(values, |items, value| {
66                        items.json_value_item(value);
67                    });
68                });
69            }
70            _ => {
71                writer.unredacted(self);
72            }
73        }
74    }
75}
76
77impl Redact for ValueContainer {
78    /// Writes the selected container payload through the shared session.
79    fn write_redacted(&self, writer: &mut RedactionWriter<'_>) {
80        match self {
81            Self::Scalar(value) => {
82                writer.tuple("ValueContainer", |fields| {
83                    fields.nested("Scalar", value);
84                });
85            }
86            Self::Collection(values) => {
87                writer.tuple("ValueContainer", |fields| {
88                    fields.nested("Collection", values);
89                });
90            }
91        }
92    }
93}
94
95impl Redact for NamedValue {
96    /// Writes the name and policy-selected value through one session.
97    fn write_redacted(&self, writer: &mut RedactionWriter<'_>) {
98        writer.record("NamedValue", |fields| {
99            fields.unredacted("name", || self.name());
100            fields.keyed_nested("value", self.name(), self.value());
101        });
102    }
103}
104
105impl Redact for NamedMultiValues {
106    /// Writes the name and policy-selected collection through one session.
107    fn write_redacted(&self, writer: &mut RedactionWriter<'_>) {
108        writer.record("NamedMultiValues", |fields| {
109            fields.unredacted("name", || self.name());
110            fields.keyed_nested("value", self.name(), self.values());
111        });
112    }
113}