adk_managed/types/
content.rs1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(tag = "type", rename_all = "snake_case")]
32#[non_exhaustive]
33pub enum ContentBlock {
34 Text {
36 text: String,
38 },
39 Image {
41 source: serde_json::Value,
43 },
44 File {
46 file_id: String,
48 },
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use serde_json::json;
55
56 #[test]
57 fn test_text_serialization_round_trip() {
58 let block = ContentBlock::Text { text: "Hello, world!".to_string() };
59
60 let serialized = serde_json::to_value(&block).unwrap();
61 assert_eq!(
62 serialized,
63 json!({
64 "type": "text",
65 "text": "Hello, world!"
66 })
67 );
68
69 let deserialized: ContentBlock = serde_json::from_value(serialized).unwrap();
70 match deserialized {
71 ContentBlock::Text { text } => assert_eq!(text, "Hello, world!"),
72 _ => panic!("Expected Text variant"),
73 }
74 }
75
76 #[test]
77 fn test_image_serialization_round_trip() {
78 let source = json!({"url": "https://example.com/img.png", "media_type": "image/png"});
79 let block = ContentBlock::Image { source: source.clone() };
80
81 let serialized = serde_json::to_value(&block).unwrap();
82 assert_eq!(
83 serialized,
84 json!({
85 "type": "image",
86 "source": {"url": "https://example.com/img.png", "media_type": "image/png"}
87 })
88 );
89
90 let deserialized: ContentBlock = serde_json::from_value(serialized).unwrap();
91 match deserialized {
92 ContentBlock::Image { source: deserialized_source } => {
93 assert_eq!(deserialized_source, source);
94 }
95 _ => panic!("Expected Image variant"),
96 }
97 }
98
99 #[test]
100 fn test_file_serialization_round_trip() {
101 let block = ContentBlock::File { file_id: "file_abc123".to_string() };
102
103 let serialized = serde_json::to_value(&block).unwrap();
104 assert_eq!(
105 serialized,
106 json!({
107 "type": "file",
108 "file_id": "file_abc123"
109 })
110 );
111
112 let deserialized: ContentBlock = serde_json::from_value(serialized).unwrap();
113 match deserialized {
114 ContentBlock::File { file_id } => assert_eq!(file_id, "file_abc123"),
115 _ => panic!("Expected File variant"),
116 }
117 }
118
119 #[test]
120 fn test_text_from_json_string() {
121 let json_str = r#"{"type": "text", "text": "sample text"}"#;
122 let block: ContentBlock = serde_json::from_str(json_str).unwrap();
123 match block {
124 ContentBlock::Text { text } => assert_eq!(text, "sample text"),
125 _ => panic!("Expected Text variant"),
126 }
127 }
128
129 #[test]
130 fn test_image_from_json_string() {
131 let json_str =
132 r#"{"type": "image", "source": {"url": "https://cdn.example.com/photo.jpg"}}"#;
133 let block: ContentBlock = serde_json::from_str(json_str).unwrap();
134 match block {
135 ContentBlock::Image { source } => {
136 assert_eq!(source["url"], "https://cdn.example.com/photo.jpg");
137 }
138 _ => panic!("Expected Image variant"),
139 }
140 }
141
142 #[test]
143 fn test_file_from_json_string() {
144 let json_str = r#"{"type": "file", "file_id": "file_xyz789"}"#;
145 let block: ContentBlock = serde_json::from_str(json_str).unwrap();
146 match block {
147 ContentBlock::File { file_id } => assert_eq!(file_id, "file_xyz789"),
148 _ => panic!("Expected File variant"),
149 }
150 }
151
152 #[test]
153 fn test_unknown_type_rejected() {
154 let json_str = r#"{"type": "video", "url": "https://example.com/vid.mp4"}"#;
155 let result: Result<ContentBlock, _> = serde_json::from_str(json_str);
156 assert!(result.is_err(), "Unknown type should be rejected");
157 }
158
159 #[test]
160 fn test_vec_content_blocks_round_trip() {
161 let blocks = vec![
162 ContentBlock::Text { text: "Here is an image:".to_string() },
163 ContentBlock::Image { source: json!({"url": "https://example.com/img.png"}) },
164 ContentBlock::File { file_id: "attachment_001".to_string() },
165 ];
166
167 let serialized = serde_json::to_value(&blocks).unwrap();
168 let deserialized: Vec<ContentBlock> = serde_json::from_value(serialized).unwrap();
169
170 assert_eq!(deserialized.len(), 3);
171 match &deserialized[0] {
172 ContentBlock::Text { text } => assert_eq!(text, "Here is an image:"),
173 _ => panic!("Expected Text"),
174 }
175 match &deserialized[1] {
176 ContentBlock::Image { source } => {
177 assert_eq!(source["url"], "https://example.com/img.png");
178 }
179 _ => panic!("Expected Image"),
180 }
181 match &deserialized[2] {
182 ContentBlock::File { file_id } => assert_eq!(file_id, "attachment_001"),
183 _ => panic!("Expected File"),
184 }
185 }
186
187 #[test]
188 fn test_debug_impl() {
189 let block = ContentBlock::Text { text: "test".to_string() };
190 let debug_str = format!("{block:?}");
191 assert!(debug_str.contains("Text"));
192 assert!(debug_str.contains("test"));
193 }
194
195 #[test]
196 fn test_clone_impl() {
197 let block = ContentBlock::Image { source: json!({"url": "https://example.com/img.png"}) };
198 let cloned = block.clone();
199 let original_json = serde_json::to_value(&block).unwrap();
200 let cloned_json = serde_json::to_value(&cloned).unwrap();
201 assert_eq!(original_json, cloned_json);
202 }
203}