use serde::{Deserialize, Serialize};
use crate::types::OutputFormat;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Effort {
Low,
Medium,
High,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct OutputConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub format: Option<OutputFormat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub effort: Option<Effort>,
}
impl OutputConfig {
pub fn new() -> Self {
Self {
format: None,
effort: None,
}
}
pub fn with_format(mut self, format: OutputFormat) -> Self {
self.format = Some(format);
self
}
pub fn with_effort(mut self, effort: Effort) -> Self {
self.effort = Some(effort);
self
}
}
impl Default for OutputConfig {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::{json, to_value};
#[test]
fn effort_serialization() {
assert_eq!(to_value(Effort::Low).unwrap(), json!("low"));
assert_eq!(to_value(Effort::Medium).unwrap(), json!("medium"));
assert_eq!(to_value(Effort::High).unwrap(), json!("high"));
}
#[test]
fn effort_deserialization() {
let low: Effort = serde_json::from_value(json!("low")).unwrap();
assert_eq!(low, Effort::Low);
let medium: Effort = serde_json::from_value(json!("medium")).unwrap();
assert_eq!(medium, Effort::Medium);
let high: Effort = serde_json::from_value(json!("high")).unwrap();
assert_eq!(high, Effort::High);
}
#[test]
fn output_config_with_effort_only() {
let config = OutputConfig::new().with_effort(Effort::High);
let json = to_value(&config).unwrap();
assert_eq!(
json,
json!({
"effort": "high"
})
);
}
#[test]
fn output_config_with_format_only() {
let config = OutputConfig::new().with_format(OutputFormat::json_schema(json!({
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"],
"additionalProperties": false
})));
let json = to_value(&config).unwrap();
assert_eq!(
json,
json!({
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"],
"additionalProperties": false
}
}
})
);
}
#[test]
fn output_config_with_both_format_and_effort() {
let config = OutputConfig::new()
.with_format(OutputFormat::json_schema(json!({
"type": "object",
"properties": {
"answer": { "type": "boolean" }
},
"required": ["answer"],
"additionalProperties": false
})))
.with_effort(Effort::Medium);
let json = to_value(&config).unwrap();
assert_eq!(
json,
json!({
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"answer": { "type": "boolean" }
},
"required": ["answer"],
"additionalProperties": false
}
},
"effort": "medium"
})
);
}
#[test]
fn output_config_empty_skips_none_fields() {
let config = OutputConfig::new();
let json = to_value(&config).unwrap();
assert_eq!(json, json!({}));
assert!(!json.as_object().unwrap().contains_key("format"));
assert!(!json.as_object().unwrap().contains_key("effort"));
}
#[test]
fn output_config_deserialization_effort_only() {
let json = json!({
"effort": "low"
});
let config: OutputConfig = serde_json::from_value(json).unwrap();
assert_eq!(config.effort, Some(Effort::Low));
assert_eq!(config.format, None);
}
#[test]
fn output_config_deserialization_format_only() {
let json = json!({
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"],
"additionalProperties": false
}
}
});
let config: OutputConfig = serde_json::from_value(json).unwrap();
assert!(config.format.is_some());
assert_eq!(config.effort, None);
}
#[test]
fn output_config_deserialization_both() {
let json = json!({
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"result": { "type": "string" }
},
"required": ["result"],
"additionalProperties": false
}
},
"effort": "high"
});
let config: OutputConfig = serde_json::from_value(json).unwrap();
assert!(config.format.is_some());
assert_eq!(config.effort, Some(Effort::High));
}
#[test]
fn output_config_deserialization_empty() {
let json = json!({});
let config: OutputConfig = serde_json::from_value(json).unwrap();
assert_eq!(config.format, None);
assert_eq!(config.effort, None);
}
#[test]
fn output_config_default() {
let config = OutputConfig::default();
assert_eq!(config.format, None);
assert_eq!(config.effort, None);
}
}