use crate::request::GuardrailRequest;
#[derive(Debug, Clone, PartialEq)]
pub enum Decision {
Allow,
Redact {
reason: String,
mutated: GuardrailRequest,
entities: Vec<String>,
},
Block {
reason: String,
code: BlockCode,
},
}
impl Decision {
pub fn should_forward(&self) -> bool {
!matches!(self, Decision::Block { .. })
}
pub fn name(&self) -> &'static str {
match self {
Decision::Allow => "allow",
Decision::Redact { .. } => "redact",
Decision::Block { .. } => "block",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BlockCode {
PromptInjection,
Toxicity,
PolicyViolation,
RateLimit,
Custom(String),
}
impl BlockCode {
pub fn as_str(&self) -> &str {
match self {
BlockCode::PromptInjection => "prompt_injection",
BlockCode::Toxicity => "toxicity",
BlockCode::PolicyViolation => "policy_violation",
BlockCode::RateLimit => "rate_limit",
BlockCode::Custom(s) => s.as_str(),
}
}
}
impl std::fmt::Display for BlockCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_should_forward_allow() {
assert!(Decision::Allow.should_forward());
}
#[test]
fn test_should_forward_block() {
let d = Decision::Block {
reason: "test".into(),
code: BlockCode::PromptInjection,
};
assert!(!d.should_forward());
}
#[test]
fn test_block_code_as_str() {
assert_eq!(BlockCode::PromptInjection.as_str(), "prompt_injection");
assert_eq!(BlockCode::Toxicity.as_str(), "toxicity");
assert_eq!(BlockCode::PolicyViolation.as_str(), "policy_violation");
assert_eq!(BlockCode::RateLimit.as_str(), "rate_limit");
assert_eq!(BlockCode::Custom("foo_bar".into()).as_str(), "foo_bar");
}
#[test]
fn test_decision_name() {
assert_eq!(Decision::Allow.name(), "allow");
assert_eq!(
Decision::Block {
reason: "x".into(),
code: BlockCode::Toxicity
}
.name(),
"block"
);
}
}