use jacquard_derive::open_union; use serde::{Deserialize, Serialize}; extern crate alloc; #[open_union] #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(tag = "$type")] enum TestUnion<'s> { #[serde(rename = "com.example.typeA")] TypeA { value: &'s str }, #[serde(rename = "com.example.typeB")] TypeB { count: i64 }, } #[test] fn test_open_union_known_variant() { let json = r#"{"$type":"com.example.typeA","value":"hello"}"#; let union: TestUnion = serde_json::from_str(json).unwrap(); match union { TestUnion::TypeA { value } => assert_eq!(value, "hello"), _ => panic!("expected TypeA"), } } #[test] fn test_open_union_unknown_variant() { use jacquard_common::types::value::Data; let json = r#"{"$type":"com.example.unknown","data":"something"}"#; let union: TestUnion = serde_json::from_str(json).unwrap(); match union { TestUnion::Unknown(Data::Object(obj)) => { // Verify the captured data contains the expected fields assert!(obj.0.contains_key("$type")); assert!(obj.0.contains_key("data")); // Check the actual values if let Some(Data::String(type_str)) = obj.0.get("$type") { assert_eq!(type_str.as_str(), "com.example.unknown"); } else { panic!("expected $type field to be a string"); } if let Some(Data::String(data_str)) = obj.0.get("data") { assert_eq!(data_str.as_str(), "something"); } else { panic!("expected data field to be a string"); } } _ => panic!("expected Unknown variant with Object data"), } } #[test] fn test_open_union_roundtrip() { let union = TestUnion::TypeB { count: 42 }; let json = serde_json::to_string(&union).unwrap(); let parsed: TestUnion = serde_json::from_str(&json).unwrap(); assert_eq!(union, parsed); // Verify the $type field is present assert!(json.contains(r#""$type":"com.example.typeB""#)); } #[test] fn test_open_union_unknown_roundtrip() { use jacquard_common::types::value::{Data, Object}; use std::collections::BTreeMap; // Create an Unknown variant with complex data let mut map = BTreeMap::new(); map.insert( "$type".into(), Data::String(jacquard_common::types::string::AtprotoStr::String( "com.example.custom".into(), )), ); map.insert("field1".into(), Data::Integer(123)); map.insert("field2".into(), Data::Boolean(false)); let union = TestUnion::Unknown(Data::Object(Object(map))); let json = serde_json::to_string(&union).unwrap(); let parsed: TestUnion = serde_json::from_str(&json).unwrap(); // Should deserialize back as Unknown since the type is not recognized match parsed { TestUnion::Unknown(Data::Object(obj)) => { assert_eq!(obj.0.len(), 3); assert!(obj.0.contains_key("$type")); assert!(obj.0.contains_key("field1")); assert!(obj.0.contains_key("field2")); // Verify values if let Some(Data::String(s)) = obj.0.get("$type") { assert_eq!(s.as_str(), "com.example.custom"); } else { panic!("expected $type to be a string"); } if let Some(Data::Integer(n)) = obj.0.get("field1") { assert_eq!(*n, 123); } else { panic!("expected field1 to be an integer"); } if let Some(Data::Boolean(b)) = obj.0.get("field2") { assert_eq!(*b, false); } else { panic!("expected field2 to be a boolean"); } } _ => panic!("expected Unknown variant"), } }