use crate::request::{RedactionRules, validate_redaction_body_path};
use super::Rule;
pub(super) fn apply_redaction_directive(
rules: &mut RedactionRules,
pair: pest::iterators::Pair<Rule>,
) -> Result<(), pest::error::Error<Rule>> {
let rule = pair.as_rule();
let span = pair.as_span();
let raw_value = pair
.into_inner()
.next()
.expect("redaction directives should include a value")
.as_str()
.trim()
.to_string();
let result = match rule {
Rule::redact_header_directive => rules.add_header_name(&raw_value),
Rule::redact_capture_directive => rules.add_capture_name(&raw_value),
Rule::redact_body_directive => {
if let Err(err) = validate_redaction_body_path(&raw_value) {
return Err(custom_error(err.to_string(), span));
}
rules.add_body_path(&raw_value)
}
_ => unreachable!("unexpected redaction directive: {:?}", rule),
};
result.map_err(|message| custom_error(message, span))
}
pub(super) fn reject_misplaced_redaction_directive(
raw: &str,
span: pest::Span<'_>,
) -> Result<(), pest::error::Error<Rule>> {
if looks_like_redaction_directive(raw) {
return Err(custom_error(
"redaction directives must appear before the first ---".to_string(),
span,
));
}
Ok(())
}
fn looks_like_redaction_directive(raw: &str) -> bool {
let trimmed = raw.trim_start();
["redact_header", "redact_capture", "redact_body"]
.iter()
.any(|prefix| {
trimmed
.strip_prefix(prefix)
.map(|remainder| remainder.trim_start().starts_with('='))
.unwrap_or(false)
})
}
fn custom_error(message: String, span: pest::Span<'_>) -> pest::error::Error<Rule> {
pest::error::Error::new_from_span(
pest::error::ErrorVariant::CustomError { message },
span,
)
}