use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum Level {
Light,
#[default]
Medium,
Heavy,
}
impl Level {
pub const ALL: [Level; 3] = [Level::Light, Level::Medium, Level::Heavy];
pub fn min_words(self) -> usize {
match self {
Level::Light => 1,
Level::Medium => 4,
Level::Heavy => 8,
}
}
}
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Level::Light => "light",
Level::Medium => "medium",
Level::Heavy => "heavy",
})
}
}
impl FromStr for Level {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"light" => Ok(Level::Light),
"medium" => Ok(Level::Medium),
"heavy" => Ok(Level::Heavy),
other => Err(format!(
"unknown level '{other}' (expected light, medium or heavy)"
)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Decision {
Approve,
Reject,
NeedsReview,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum Reason {
Useful,
TooShort,
StockPhrase,
Duplicate,
InjectionAttempt,
SpamPromo,
Toxic,
Generic,
OffTopic,
NotSpecific,
CustomRule,
LowConfidence,
ModelUnavailable,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Comment {
pub text: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
}
impl Comment {
pub fn new(text: impl Into<String>) -> Self {
Comment {
text: text.into(),
..Comment::default()
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Verdict {
pub verdict: Decision,
pub reason: Reason,
pub confidence: f64,
pub level: Level,
pub model: Option<String>,
#[schemars(schema_with = "non_negative_integer")]
pub latency_ms: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rule: Option<String>,
}
fn non_negative_integer(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
schemars::json_schema!({ "type": "integer", "minimum": 0 })
}