qubit-redact 0.9.0

Rule-driven redaction for fields, diagnostics, HTTP data, and Rust domain objects
Documentation
// =============================================================================
//    Copyright (c) 2026 Haixing Hu.
//
//    SPDX-License-Identifier: Apache-2.0
//
//    Licensed under the Apache License, Version 2.0.
// =============================================================================
//! Borrowed adapter for values classified by a sibling policy key.

use serde::Serialize;
use serde::Serializer;

use super::redact_level_serialize::RedactLevelSerialize;
use super::redact_serialize_scope::RedactSerializeScope;
use super::redacted_level_serialize_ref::RedactedLevelSerializeRef;
use crate::RedactionPolicy;
use crate::policy::ResolvedField;

/// Borrowed serializer adapter for one keyed value.
#[doc(hidden)]
pub struct RedactedKeyedSerializeRef<'value, 'key, 'policy, T: ?Sized, K: ?Sized> {
    /// Borrowed source value.
    value: &'value T,
    /// Runtime key used to classify the source value.
    key: &'key K,
    /// Policy used to classify the key and mask the value.
    policy: &'policy RedactionPolicy,
}

impl<'value, 'key, 'policy, T: ?Sized, K: ?Sized> RedactedKeyedSerializeRef<'value, 'key, 'policy, T, K> {
    /// Creates a policy-carrying borrowed keyed-value adapter.
    #[must_use]
    #[inline(always)]
    pub fn new(value: &'value T, key: &'key K, policy: &'policy RedactionPolicy) -> Self {
        Self { value, key, policy }
    }
}

impl<T, K> Serialize for RedactedKeyedSerializeRef<'_, '_, '_, T, K>
where
    T: ?Sized + RedactLevelSerialize + Serialize,
    K: ?Sized + AsRef<str>,
{
    /// Runs this borrowed adapter under the shared policy and resource scope.
    ///
    /// # Errors
    ///
    /// Propagates admission failures and errors from the downstream serializer.
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let _scope = RedactSerializeScope::new(self.policy);
        let key = self.key.as_ref();
        super::redact_serialize_scope::check_key_bytes::<S::Error>(key)?;
        if self.policy.is_disabled() {
            return super::budget_serialize::BudgetSerialize::new(self.value).serialize(serializer);
        }
        match super::resolve_keyed_field(self.policy, key) {
            ResolvedField::Sensitive { sensitivity } => {
                RedactedLevelSerializeRef::new(self.value, self.policy, sensitivity).serialize(serializer)
            }
            ResolvedField::PassThrough => {
                super::budget_serialize::BudgetSerialize::new(self.value).serialize(serializer)
            }
        }
    }
}