1use serde::{Deserialize, Serialize};
2
3use crate::state::{HierarchyKind, SourceLocation};
4
5pub const PROTOCOL_VERSION: u16 = 1;
6
7#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
9pub struct Envelope<T> {
10 pub version: u16,
11 pub request_id: Option<u64>,
12 pub payload: T,
13}
14
15impl<T> Envelope<T> {
16 pub fn new(request_id: Option<u64>, payload: T) -> Self {
17 Self {
18 version: PROTOCOL_VERSION,
19 request_id,
20 payload,
21 }
22 }
23}
24
25#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
26#[serde(tag = "type", rename_all = "snake_case")]
27pub enum IpcRequest {
28 FocusSymbol {
29 hierarchy: HierarchyKind,
30 symbol: String,
31 location: Option<SourceLocation>,
32 },
33}
34
35#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
36#[serde(tag = "type", rename_all = "snake_case")]
37pub enum IpcResponse {
38 Accepted,
39 Error { message: String },
40}
41
42#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
43#[serde(tag = "type", rename_all = "snake_case")]
44pub enum IpcEvent {
45 OpenLocation {
48 uri: String,
49 line: u32,
50 character: u32,
51 },
52}
53
54#[cfg(test)]
55mod tests {
56 use super::{Envelope, IpcEvent, IpcRequest, PROTOCOL_VERSION};
57 use crate::state::HierarchyKind;
58
59 #[test]
60 fn serializes_a_versioned_tagged_request() {
61 let message = Envelope::new(
62 Some(7),
63 IpcRequest::FocusSymbol {
64 hierarchy: HierarchyKind::Call,
65 symbol: "run".to_owned(),
66 location: None,
67 },
68 );
69
70 let value = serde_json::to_value(message).unwrap();
71 assert_eq!(value["version"], PROTOCOL_VERSION);
72 assert_eq!(value["request_id"], 7);
73 assert_eq!(value["payload"]["type"], "focus_symbol");
74 }
75
76 #[test]
77 fn serializes_open_location_with_zero_based_coordinates() {
78 let message = Envelope::new(
79 None,
80 IpcEvent::OpenLocation {
81 uri: "file:///workspace/main.py".to_owned(),
82 line: 4,
83 character: 2,
84 },
85 );
86
87 let encoded = serde_json::to_string(&message).unwrap();
88 assert!(!encoded.contains('\n'));
89 let value: serde_json::Value = serde_json::from_str(&encoded).unwrap();
90 assert_eq!(value["version"], PROTOCOL_VERSION);
91 assert!(value["request_id"].is_null());
92 assert_eq!(value["payload"]["type"], "open_location");
93 assert_eq!(value["payload"]["line"], 4);
94 assert_eq!(value["payload"]["character"], 2);
95 }
96}