use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Critique {
pub pass: bool,
pub feedback: String,
#[serde(default)]
pub iteration: u8,
}
impl Critique {
pub fn pass(feedback: impl Into<String>) -> Self {
Self {
pass: true,
feedback: feedback.into(),
iteration: 0,
}
}
pub fn fail(feedback: impl Into<String>) -> Self {
Self {
pass: false,
feedback: feedback.into(),
iteration: 0,
}
}
pub fn pass_str(feedback: &str) -> Self {
Self::pass(feedback.to_string())
}
pub fn fail_str(feedback: &str) -> Self {
Self::fail(feedback.to_string())
}
pub(crate) fn with_iteration(mut self, iter: u8) -> Self {
self.iteration = iter;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[non_exhaustive]
pub struct QualityMetadata {
pub iterations_used: u8,
pub max_iterations: u8,
pub passed: bool,
pub final_critique: Option<Critique>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pass_fail_constructors() {
let c = Critique::pass("good");
assert!(c.pass);
assert_eq!(c.iteration, 0);
let c = Critique::fail("bad");
assert!(!c.pass);
}
#[test]
fn with_iteration_stamps_index() {
let c = Critique::pass("ok").with_iteration(3);
assert_eq!(c.iteration, 3);
}
#[test]
fn fail_str_accepts_literal_without_inference_ambiguity() {
let c = Critique::fail_str("too short");
assert!(!c.pass);
assert_eq!(c.feedback, "too short");
}
#[test]
fn pass_str_accepts_literal() {
let c = Critique::pass_str("ok");
assert!(c.pass);
assert_eq!(c.feedback, "ok");
}
#[test]
fn round_trip_json() {
let c = Critique::pass("hi");
let s = serde_json::to_string(&c).unwrap();
let c2: Critique = serde_json::from_str(&s).unwrap();
assert_eq!(c.feedback, c2.feedback);
}
}