use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct IdValue {
#[serde(rename = "@id")]
pub id: String,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(untagged)]
pub enum Id {
Id(IdValue),
IdArray(Vec<IdValue>),
}
impl Id {
pub fn contains_id(&self, target_id: &str) -> bool {
match self {
Id::Id(id_value) => &id_value.id == target_id,
Id::IdArray(id_values) => id_values.iter().any(|id_val| &id_val.id == target_id),
}
}
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum License {
Id(Id),
Description(String),
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DataType {
Term(String),
TermArray(Vec<String>),
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(untagged)]
pub enum DynamicEntity {
EntityString(String),
EntityVecString(Vec<String>),
EntityId(Id),
EntityIdVec(Vec<Id>),
EntityBool(bool),
Entityi64(i64),
Entityf64(f64),
EntityVeci64(Vec<i64>),
EntityVecf64(Vec<f64>),
EntityVec(Vec<DynamicEntity>),
EntityObject(HashMap<String, DynamicEntity>),
EntityVecObject(Vec<HashMap<String, DynamicEntity>>),
NestedDynamicEntity(Box<DynamicEntity>),
Fallback(serde_json::Value),
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_contains_id_single() {
let id = Id::Id(IdValue {
id: "test_id".to_string(),
});
assert!(id.contains_id("test_id"));
assert!(!id.contains_id("other_id"));
}
#[test]
fn test_contains_id_in_array() {
let ids = Id::IdArray(vec![
IdValue {
id: "test_id1".to_string(),
},
IdValue {
id: "test_id2".to_string(),
},
]);
assert!(ids.contains_id("test_id1"));
assert!(ids.contains_id("test_id2"));
assert!(!ids.contains_id("other_id"));
}
#[test]
fn test_contains_id_empty_string() {
let id = Id::Id(IdValue { id: "".to_string() });
assert!(!id.contains_id("test_id"));
}
#[test]
fn test_serialization_deserialization_id() {
let id = Id::Id(IdValue {
id: "test_id".to_string(),
});
let serialized = serde_json::to_string(&id).unwrap();
let deserialized: Id = serde_json::from_str(&serialized).unwrap();
assert_eq!(serialized, r#"{"@id":"test_id"}"#);
assert!(deserialized.contains_id("test_id"));
}
#[test]
fn test_dynamic_entity_fallback() {
let json_value = json!({"unexpected": "data"});
let entity = DynamicEntity::Fallback(json_value.clone());
match entity {
DynamicEntity::Fallback(value) => assert_eq!(value, json_value),
_ => panic!("Fallback variant expected"),
}
}
#[test]
fn test_dynamic_entity_string() {
let entity = DynamicEntity::EntityString("test".to_string());
match entity {
DynamicEntity::EntityString(value) => assert_eq!(value, "test"),
_ => panic!("EntityString variant expected"),
}
}
#[test]
fn test_dynamic_entity_bool() {
let entity = DynamicEntity::EntityBool(true);
match entity {
DynamicEntity::EntityBool(value) => assert!(value),
_ => panic!("EntityBool variant expected"),
}
}
#[test]
fn test_dynamic_entity_id() {
let id = Id::Id(IdValue {
id: "entity_id".to_string(),
});
let entity = DynamicEntity::EntityId(id.clone());
match entity {
DynamicEntity::EntityId(e_id) => assert_eq!(e_id, id),
_ => panic!("EntityId variant expected"),
}
}
#[test]
fn test_dynamic_entity_i64() {
let entity = DynamicEntity::Entityi64(42);
match entity {
DynamicEntity::Entityi64(value) => assert_eq!(value, 42),
_ => panic!("Entityi64 variant expected"),
}
}
#[test]
fn test_dynamic_entity_f64() {
let entity = DynamicEntity::Entityf64(3.14);
match entity {
DynamicEntity::Entityf64(value) => assert!((value - 3.14).abs() < f64::EPSILON),
_ => panic!("Entityf64 variant expected"),
}
}
#[test]
fn test_dynamic_entity_fallback_empty() {
let json_value = json!({});
let entity = DynamicEntity::Fallback(json_value.clone());
match entity {
DynamicEntity::Fallback(value) => assert_eq!(value, json_value),
_ => panic!("Fallback variant expected"),
}
}
#[test]
fn test_license_id() {
let license = License::Id(Id::Id(IdValue {
id: "license_id".to_string(),
}));
match license {
License::Id(Id::Id(id_value)) => assert_eq!(id_value.id, "license_id"),
_ => panic!("License::Id variant expected"),
}
}
#[test]
fn test_license_description() {
let license = License::Description("Creative Commons".to_string());
match license {
License::Description(desc) => assert_eq!(desc, "Creative Commons"),
_ => panic!("License::Description variant expected"),
}
}
#[test]
fn test_data_type_term() {
let data_type = DataType::Term("Text".to_string());
match data_type {
DataType::Term(term) => assert_eq!(term, "Text"),
_ => panic!("DataType::Term variant expected"),
}
}
#[test]
fn test_data_type_term_array() {
let data_type = DataType::TermArray(vec!["Text".to_string(), "Image".to_string()]);
match data_type {
DataType::TermArray(terms) => assert_eq!(terms, vec!["Text", "Image"]),
_ => panic!("DataType::TermArray variant expected"),
}
}
}