Skip to main content

adk_ui/a2ui/
encoding.rs

1use serde_json::Error as JsonError;
2
3use super::messages::A2uiMessage;
4
5/// Encode a single A2UI message as a JSON line.
6pub fn encode_message_line(message: &A2uiMessage) -> Result<String, JsonError> {
7    let mut line = serde_json::to_string(message)?;
8    line.push('\n');
9    Ok(line)
10}
11
12/// Encode an iterator of A2UI messages as JSONL (newline-delimited JSON).
13pub fn encode_jsonl<I>(messages: I) -> Result<String, JsonError>
14where
15    I: IntoIterator<Item = A2uiMessage>,
16{
17    let mut output = String::new();
18    for message in messages {
19        output.push_str(&serde_json::to_string(&message)?);
20        output.push('\n');
21    }
22    Ok(output)
23}
24
25/// Encode an iterator of A2UI messages as JSONL bytes.
26pub fn encode_jsonl_bytes<I>(messages: I) -> Result<Vec<u8>, JsonError>
27where
28    I: IntoIterator<Item = A2uiMessage>,
29{
30    Ok(encode_jsonl(messages)?.into_bytes())
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36    use crate::a2ui::messages::{
37        A2uiMessage, CreateSurface, CreateSurfaceMessage, DeleteSurface, DeleteSurfaceMessage,
38    };
39
40    #[test]
41    fn encodes_single_line_with_newline() {
42        let message = A2uiMessage::CreateSurface(CreateSurfaceMessage::new(CreateSurface {
43            surface_id: "main".to_string(),
44            catalog_id: "catalog".to_string(),
45            theme: None,
46            send_data_model: None,
47            components: None,
48            data_model: None,
49        }));
50
51        let line = encode_message_line(&message).unwrap();
52        assert!(line.ends_with('\n'));
53
54        let value: serde_json::Value = serde_json::from_str(line.trim()).unwrap();
55        assert_eq!(value["createSurface"]["surfaceId"], "main");
56        assert_eq!(value["version"], "v0.9.1");
57    }
58
59    #[test]
60    fn encodes_multiple_messages_as_jsonl() {
61        let create = A2uiMessage::CreateSurface(CreateSurfaceMessage::new(CreateSurface {
62            surface_id: "main".to_string(),
63            catalog_id: "catalog".to_string(),
64            theme: None,
65            send_data_model: None,
66            components: None,
67            data_model: None,
68        }));
69        let delete = A2uiMessage::DeleteSurface(DeleteSurfaceMessage::new(DeleteSurface {
70            surface_id: "main".to_string(),
71        }));
72
73        let jsonl = encode_jsonl(vec![create, delete]).unwrap();
74        let lines: Vec<&str> = jsonl.trim_end().split('\n').collect();
75        assert_eq!(lines.len(), 2);
76    }
77}