kernel_sidecar/jupyter/
response.rs

1/*
2This file is all about deserializing messages coming from Kernel to Client.
3
4zeromq::ZmqMessage -> WireProtocol -> Response -> Message<T> with Jupyter message content T
5*/
6use crate::jupyter::constants::EMPTY_DICT_BYTES;
7use crate::jupyter::header::Header;
8use crate::jupyter::iopub_content::clear_output::ClearOutput;
9use crate::jupyter::iopub_content::display_data::{DisplayData, UpdateDisplayData};
10use crate::jupyter::iopub_content::errors::Error;
11use crate::jupyter::iopub_content::execute_input::ExecuteInput;
12use crate::jupyter::iopub_content::execute_result::ExecuteResult;
13use crate::jupyter::iopub_content::status::Status;
14use crate::jupyter::iopub_content::stream::Stream;
15use crate::jupyter::message::Message;
16use crate::jupyter::metadata::Metadata;
17use crate::jupyter::shell_content::execute::ExecuteReply;
18use crate::jupyter::shell_content::kernel_info::KernelInfoReply;
19use crate::jupyter::wire_protocol::WireProtocol;
20use serde::{Deserialize, Serialize};
21
22use zeromq::ZmqMessage;
23
24#[derive(Debug, Serialize, Deserialize)]
25pub struct UnmodeledContent(serde_json::Value);
26
27#[derive(Debug)]
28pub enum Response {
29    // Request/reply from shell channel
30    KernelInfo(Message<KernelInfoReply>),
31    Execute(Message<ExecuteReply>),
32    // Messages from iopub channel
33    Status(Message<Status>),
34    ExecuteInput(Message<ExecuteInput>),
35    ExecuteResult(Message<ExecuteResult>),
36    Stream(Message<Stream>),
37    DisplayData(Message<DisplayData>),
38    UpdateDisplayData(Message<UpdateDisplayData>),
39    ClearOutput(Message<ClearOutput>),
40    // Errors
41    Error(Message<Error>),
42    // Messages I haven't modeled yet, crate is WIP
43    Unmodeled(Message<UnmodeledContent>),
44}
45
46impl Response {
47    pub fn parent_msg_id(&self) -> Option<String> {
48        // return parent_msg_id from header
49        match self {
50            Response::Status(msg) => msg.parent_msg_id(),
51            Response::KernelInfo(msg) => msg.parent_msg_id(),
52            Response::Execute(msg) => msg.parent_msg_id(),
53            Response::ExecuteInput(msg) => msg.parent_msg_id(),
54            Response::ExecuteResult(msg) => msg.parent_msg_id(),
55            Response::Stream(msg) => msg.parent_msg_id(),
56            Response::DisplayData(msg) => msg.parent_msg_id(),
57            Response::UpdateDisplayData(msg) => msg.parent_msg_id(),
58            Response::ClearOutput(msg) => msg.parent_msg_id(),
59            Response::Error(msg) => msg.parent_msg_id(),
60            Response::Unmodeled(msg) => msg.parent_msg_id(),
61        }
62    }
63
64    pub fn msg_type(&self) -> String {
65        // return msg_type from header
66        match self {
67            Response::Status(msg) => msg.header.msg_type.to_owned(),
68            Response::KernelInfo(msg) => msg.header.msg_type.to_owned(),
69            Response::Execute(msg) => msg.header.msg_type.to_owned(),
70            Response::ExecuteInput(msg) => msg.header.msg_type.to_owned(),
71            Response::ExecuteResult(msg) => msg.header.msg_type.to_owned(),
72            Response::Stream(msg) => msg.header.msg_type.to_owned(),
73            Response::DisplayData(msg) => msg.header.msg_type.to_owned(),
74            Response::UpdateDisplayData(msg) => msg.header.msg_type.to_owned(),
75            Response::ClearOutput(msg) => msg.header.msg_type.to_owned(),
76            Response::Error(msg) => msg.header.msg_type.to_owned(),
77            Response::Unmodeled(msg) => {
78                let real_msg_type = msg.header.msg_type.to_owned();
79                format!("unmodeled_{}", real_msg_type)
80            }
81        }
82    }
83}
84
85impl From<WireProtocol> for Response {
86    fn from(wp: WireProtocol) -> Self {
87        let header: Header = wp.header.into();
88        let parent_header = match wp.parent_header == EMPTY_DICT_BYTES.clone() {
89            true => None,
90            false => Some(wp.parent_header.into()),
91        };
92        let metadata: Metadata = wp.metadata.into();
93        match header.msg_type.as_str() {
94            "status" => {
95                let content: Status = wp.content.into();
96                let msg: Message<Status> = Message {
97                    header,
98                    parent_header,
99                    metadata: Some(metadata),
100                    content,
101                };
102                Response::Status(msg)
103            }
104            "kernel_info_reply" => {
105                let content: KernelInfoReply = wp.content.into();
106                let msg: Message<KernelInfoReply> = Message {
107                    header,
108                    parent_header,
109                    metadata: Some(metadata),
110                    content,
111                };
112                Response::KernelInfo(msg)
113            }
114            "execute_reply" => {
115                let content: ExecuteReply = wp.content.into();
116                let msg: Message<ExecuteReply> = Message {
117                    header,
118                    parent_header,
119                    metadata: Some(metadata),
120                    content,
121                };
122                Response::Execute(msg)
123            }
124            "execute_input" => {
125                let content: ExecuteInput = wp.content.into();
126                let msg: Message<ExecuteInput> = Message {
127                    header,
128                    parent_header,
129                    metadata: Some(metadata),
130                    content,
131                };
132                Response::ExecuteInput(msg)
133            }
134            "execute_result" => {
135                let content: ExecuteResult = wp.content.into();
136                let msg: Message<ExecuteResult> = Message {
137                    header,
138                    parent_header,
139                    metadata: Some(metadata),
140                    content,
141                };
142                Response::ExecuteResult(msg)
143            }
144            "stream" => {
145                let content: Stream = wp.content.into();
146                let msg: Message<Stream> = Message {
147                    header,
148                    parent_header,
149                    metadata: Some(metadata),
150                    content,
151                };
152                Response::Stream(msg)
153            }
154            "display_data" => {
155                let content: DisplayData = wp.content.into();
156                let msg: Message<DisplayData> = Message {
157                    header,
158                    parent_header,
159                    metadata: Some(metadata),
160                    content,
161                };
162                Response::DisplayData(msg)
163            }
164            "update_display_data" => {
165                let content: UpdateDisplayData = wp.content.into();
166                let msg: Message<UpdateDisplayData> = Message {
167                    header,
168                    parent_header,
169                    metadata: Some(metadata),
170                    content,
171                };
172                Response::UpdateDisplayData(msg)
173            }
174            "clear_output" => {
175                let content: ClearOutput = wp.content.into();
176                let msg: Message<ClearOutput> = Message {
177                    header,
178                    parent_header,
179                    metadata: Some(metadata),
180                    content,
181                };
182                Response::ClearOutput(msg)
183            }
184            "error" => {
185                let content: Error = wp.content.into();
186                let msg: Message<Error> = Message {
187                    header,
188                    parent_header,
189                    metadata: Some(metadata),
190                    content,
191                };
192                Response::Error(msg)
193            }
194            _ => {
195                let content: UnmodeledContent = serde_json::from_slice(&wp.content)
196                    .expect("Error deserializing unmodeled content");
197                let msg: Message<UnmodeledContent> = Message {
198                    header,
199                    parent_header,
200                    metadata: Some(metadata),
201                    content,
202                };
203                Response::Unmodeled(msg)
204            }
205        }
206    }
207}
208
209impl From<ZmqMessage> for Response {
210    fn from(msg: ZmqMessage) -> Self {
211        let wp: WireProtocol = msg.into();
212        wp.into()
213    }
214}