use std::io::Write;
use serde_json::Value;
use serde_json::to_writer;
use super::BoundedBodyWriter;
use super::markers::UNKEYED_JSON;
use crate::UnkeyedJsonValuePolicy;
use crate::formats::http::FieldRedactor;
use crate::formats::json::internal::JsonRedactionState;
use crate::formats::json::internal::JsonUnkeyedValuePolicy;
#[must_use]
pub(in crate::formats::http) fn redact(
redactor: &FieldRedactor<'_>,
value: &mut Value,
unkeyed: UnkeyedJsonValuePolicy,
) -> bool {
let unkeyed = match unkeyed {
UnkeyedJsonValuePolicy::PassThrough => JsonUnkeyedValuePolicy::PassThrough,
UnkeyedJsonValuePolicy::Redact => JsonUnkeyedValuePolicy::Redact { marker: UNKEYED_JSON },
};
let outcome = JsonRedactionState::new(
redactor.base_rules(),
redactor.context_rules(),
redactor.masking(),
unkeyed,
)
.redact(value);
match outcome {
crate::formats::json::internal::JsonRedactionOutcome::Complete { passed_unkeyed } => passed_unkeyed,
}
}
#[must_use]
pub(in crate::formats::http) fn serialize_bounded(value: &Value, max_output_bytes: usize) -> Option<(String, bool)> {
let mut writer = BoundedBodyWriter::new(max_output_bytes);
if to_writer(&mut writer, value).is_err() {
return writer.into_string().map(|text| (text, true));
}
writer.flush().ok()?;
writer.into_string().map(|text| (text, false))
}
#[must_use]
pub(in crate::formats::http) fn redact_ndjson_values(
redactor: &FieldRedactor<'_>,
lines: &mut [Option<Value>],
trailing_newline: bool,
unkeyed: UnkeyedJsonValuePolicy,
max_output_bytes: usize,
) -> Option<(String, bool, bool)> {
let mut output = BoundedBodyWriter::new(max_output_bytes);
let mut passed = false;
for (index, line) in lines.iter_mut().enumerate() {
if index > 0 && output.write_all(b"\n").is_err() {
return output.into_string().map(|text| (text, passed, true));
}
let Some(value) = line else {
continue;
};
passed |= redact(redactor, value, unkeyed);
if to_writer(&mut output, value).is_err() {
return output.into_string().map(|text| (text, passed, true));
}
}
if trailing_newline && output.write_all(b"\n").is_err() {
return output.into_string().map(|text| (text, passed, true));
}
output.into_string().map(|text| (text, passed, false))
}