use crate::error::ModelError;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct ArticleEnvelope {
pub schema_version: String,
pub payload: serde_json::Value,
}
impl ArticleEnvelope {
pub fn new(schema_version: &str, payload: serde_json::Value) -> Self {
Self {
schema_version: schema_version.to_string(),
payload,
}
}
pub fn parse<T>(&self) -> Result<T, ModelError>
where
T: for<'de> serde::Deserialize<'de>,
{
match self.schema_version.as_str() {
"2024.1" | "2024.2" => serde_json::from_value(self.payload.clone())
.map_err(|e| ModelError::DeserializationError(e.to_string())),
_ => Err(ModelError::UnsupportedSchemaVersion(
self.schema_version.clone(),
)),
}
}
pub fn schema_version(&self) -> &str {
&self.schema_version
}
pub fn is_supported(&self) -> bool {
matches!(self.schema_version.as_str(), "2024.1" | "2024.2")
}
}
pub const SUPPORTED_SCHEMA_VERSIONS: &[&str] = &["2024.1", "2024.2"];
pub const DEFAULT_SCHEMA_VERSION: &str = "2024.2";
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_envelope_creation() {
let envelope = ArticleEnvelope::new("2024.2", serde_json::json!({"name": "Test"}));
assert_eq!(envelope.schema_version(), "2024.2");
assert!(envelope.is_supported());
}
#[test]
fn test_envelope_parse() {
let envelope =
ArticleEnvelope::new("2024.2", serde_json::json!({"name": "Test", "value": 42}));
#[derive(serde::Deserialize, Debug, PartialEq)]
struct TestData {
name: String,
value: i32,
}
let data: TestData = envelope.parse().unwrap();
assert_eq!(data.name, "Test");
assert_eq!(data.value, 42);
}
#[test]
fn test_unsupported_version() {
let envelope = ArticleEnvelope::new("1999.1", serde_json::json!({}));
assert!(!envelope.is_supported());
let result: Result<serde_json::Value, _> = envelope.parse();
assert!(result.is_err());
}
#[test]
fn test_supported_versions() {
assert!(SUPPORTED_SCHEMA_VERSIONS.contains(&"2024.1"));
assert!(SUPPORTED_SCHEMA_VERSIONS.contains(&"2024.2"));
assert_eq!(DEFAULT_SCHEMA_VERSION, "2024.2");
}
}