use crate::validation::{Context, ValidateWithContext, ValidationOptions};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Default)]
pub struct Info {
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub version: String,
#[serde(flatten)]
#[serde(with = "crate::common::extensions")]
#[serde(skip_serializing_if = "Option::is_none")]
pub extensions: Option<BTreeMap<String, serde_json::Value>>,
}
impl ValidateWithContext for Info {
fn validate_with_context(&self, ctx: &mut Context) {
if !ctx.is_option(ValidationOptions::IgnoreEmptyInfoTitle) {
ctx.require_non_empty("title", &self.title);
}
if !ctx.is_option(ValidationOptions::IgnoreEmptyInfoVersion) {
ctx.require_non_empty("version", &self.version);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use enumset::EnumSet;
use serde_json::json;
#[test]
fn deserialize_minimal_info_round_trips() {
let info: Info = serde_json::from_value(json!({ "title": "T", "version": "1.0" })).unwrap();
assert_eq!(info.title, "T");
assert_eq!(info.version, "1.0");
assert!(info.extensions.is_none());
assert_eq!(
serde_json::to_value(&info).unwrap(),
json!({ "title": "T", "version": "1.0" })
);
}
#[test]
fn full_info_round_trips() {
let info: Info = serde_json::from_value(json!({
"title": "T", "summary": "S", "description": "D", "version": "1.0", "x-team": "p"
}))
.unwrap();
assert_eq!(info.summary.as_deref(), Some("S"));
assert_eq!(info.description.as_deref(), Some("D"));
let v = serde_json::to_value(&info).unwrap();
assert_eq!(v["summary"], json!("S"));
assert_eq!(v["description"], json!("D"));
assert_eq!(v["x-team"], json!("p"));
}
#[test]
fn validate_rejects_empty_title_and_version() {
let mut c = Context::with_path(EnumSet::empty(), "#.info");
Info::default().validate_with_context(&mut c);
assert!(
c.errors
.iter()
.any(|e| e == "#.info.title: must not be empty")
);
assert!(
c.errors
.iter()
.any(|e| e == "#.info.version: must not be empty")
);
}
}