1pub use super::generated_api::api::{
2 action::{Action as ProtobufAction, Position as ProtobufPosition},
3 event::{
4 event::Payload as ProtobufEventPayload,
5 layout_parsing_error::ErrorType as ProtobufLayoutParsingErrorType,
6 pane_scrollback_response, ActionCompletePayload as ProtobufActionCompletePayload,
7 AvailableLayoutInfoPayload as ProtobufAvailableLayoutInfoPayload,
8 ClientInfo as ProtobufClientInfo, ClientPaneHistory as ProtobufClientPaneHistory,
9 ClientTabHistory as ProtobufClientTabHistory,
10 CommandChangedPayload as ProtobufCommandChangedPayload, ContextItem as ProtobufContextItem,
11 CopyDestination as ProtobufCopyDestination, CwdChangedPayload as ProtobufCwdChangedPayload,
12 Event as ProtobufEvent, EventNameList as ProtobufEventNameList,
13 EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata,
14 HostTerminalThemeChangedPayload as ProtobufHostTerminalThemeChangedPayload,
15 HostTerminalThemeIndication as ProtobufHostTerminalThemeIndication,
16 InputModeKeybinds as ProtobufInputModeKeybinds, KdlError as ProtobufKdlError,
17 KdlErrorVariant as ProtobufKdlErrorVariant, KeyBind as ProtobufKeyBind,
18 LayoutInfo as ProtobufLayoutInfo, LayoutMetadata as ProtobufLayoutMetadata,
19 LayoutParsingError as ProtobufLayoutParsingError,
20 LayoutWithError as ProtobufLayoutWithError, ModeUpdatePayload as ProtobufModeUpdatePayload,
21 PaneContents as ProtobufPaneContents, PaneContentsEntry as ProtobufPaneContentsEntry,
22 PaneId as ProtobufPaneId, PaneInfo as ProtobufPaneInfo,
23 PaneManifest as ProtobufPaneManifest, PaneMetadata as ProtobufPaneMetadata,
24 PaneRenderReportPayload as ProtobufPaneRenderReportPayload,
25 PaneScrollbackResponse as ProtobufPaneScrollbackResponse, PaneType as ProtobufPaneType,
26 PluginConfigurationChangedPayload as ProtobufPluginConfigurationChangedPayload,
27 PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession,
28 SelectedText as ProtobufSelectedText, SessionManifest as ProtobufSessionManifest,
29 SyntaxError as ProtobufSyntaxError, TabInfo as ProtobufTabInfo,
30 TabMetadata as ProtobufTabMetadata, UserActionPayload as ProtobufUserActionPayload,
31 WebServerStatusPayload as ProtobufWebServerStatusPayload, WebSharing as ProtobufWebSharing,
32 *,
33 },
34 input_mode::InputMode as ProtobufInputMode,
35 key::Key as ProtobufKey,
36 style::Style as ProtobufStyle,
37};
38#[allow(hidden_glob_reexports)]
39use crate::data::{
40 ClientId, ClientInfo, CopyDestination, Event, EventType, FileMetadata, HostTerminalThemeMode,
41 InputMode, KeyWithModifier, LayoutInfo, LayoutMetadata, ModeInfo, Mouse, PaneContents, PaneId,
42 PaneInfo, PaneManifest, PaneMetadata, PaneScrollbackResponse, PermissionStatus,
43 PluginCapabilities, PluginInfo, SelectedText, SessionInfo, Style, TabInfo, TabMetadata,
44 WebServerStatus, WebSharing,
45};
46
47use crate::errors::prelude::*;
48use crate::input::actions::Action;
49
50use std::collections::{BTreeMap, HashMap, HashSet};
51use std::convert::TryFrom;
52use std::net::IpAddr;
53use std::path::PathBuf;
54use std::str::FromStr;
55use std::time::Duration;
56
57impl TryFrom<ProtobufEvent> for Event {
58 type Error = &'static str;
59 fn try_from(protobuf_event: ProtobufEvent) -> Result<Self, &'static str> {
60 match ProtobufEventType::from_i32(protobuf_event.name) {
61 Some(ProtobufEventType::ModeUpdate) => match protobuf_event.payload {
62 Some(ProtobufEventPayload::ModeUpdatePayload(protobuf_mode_update_payload)) => {
63 let mode_info: ModeInfo = protobuf_mode_update_payload.try_into()?;
64 Ok(Event::ModeUpdate(mode_info))
65 },
66 _ => Err("Malformed payload for the ModeUpdate Event"),
67 },
68 Some(ProtobufEventType::TabUpdate) => match protobuf_event.payload {
69 Some(ProtobufEventPayload::TabUpdatePayload(protobuf_tab_info_payload)) => {
70 let mut tab_infos: Vec<TabInfo> = vec![];
71 for protobuf_tab_info in protobuf_tab_info_payload.tab_info {
72 tab_infos.push(TabInfo::try_from(protobuf_tab_info)?);
73 }
74 Ok(Event::TabUpdate(tab_infos))
75 },
76 _ => Err("Malformed payload for the TabUpdate Event"),
77 },
78 Some(ProtobufEventType::PaneUpdate) => match protobuf_event.payload {
79 Some(ProtobufEventPayload::PaneUpdatePayload(protobuf_pane_update_payload)) => {
80 let mut pane_manifest: HashMap<usize, Vec<PaneInfo>> = HashMap::new();
81 for protobuf_pane_manifest in protobuf_pane_update_payload.pane_manifest {
82 let tab_index = protobuf_pane_manifest.tab_index as usize;
83 let mut panes = vec![];
84 for protobuf_pane_info in protobuf_pane_manifest.panes {
85 panes.push(protobuf_pane_info.try_into()?);
86 }
87 if pane_manifest.contains_key(&tab_index) {
88 return Err("Duplicate tab definition in pane manifest");
89 }
90 pane_manifest.insert(tab_index, panes);
91 }
92 Ok(Event::PaneUpdate(PaneManifest {
93 panes: pane_manifest,
94 }))
95 },
96 _ => Err("Malformed payload for the PaneUpdate Event"),
97 },
98 Some(ProtobufEventType::Key) => match protobuf_event.payload {
99 Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => {
100 Ok(Event::Key(protobuf_key.try_into()?))
101 },
102 _ => Err("Malformed payload for the Key Event"),
103 },
104 Some(ProtobufEventType::Mouse) => match protobuf_event.payload {
105 Some(ProtobufEventPayload::MouseEventPayload(protobuf_mouse)) => {
106 Ok(Event::Mouse(protobuf_mouse.try_into()?))
107 },
108 _ => Err("Malformed payload for the Mouse Event"),
109 },
110 Some(ProtobufEventType::Timer) => match protobuf_event.payload {
111 Some(ProtobufEventPayload::TimerPayload(seconds)) => {
112 Ok(Event::Timer(seconds as f64))
113 },
114 _ => Err("Malformed payload for the Timer Event"),
115 },
116 Some(ProtobufEventType::CopyToClipboard) => match protobuf_event.payload {
117 Some(ProtobufEventPayload::CopyToClipboardPayload(copy_to_clipboard)) => {
118 let protobuf_copy_to_clipboard =
119 ProtobufCopyDestination::from_i32(copy_to_clipboard)
120 .ok_or("Malformed copy to clipboard payload")?;
121 Ok(Event::CopyToClipboard(
122 protobuf_copy_to_clipboard.try_into()?,
123 ))
124 },
125 _ => Err("Malformed payload for the Copy To Clipboard Event"),
126 },
127 Some(ProtobufEventType::SystemClipboardFailure) => match protobuf_event.payload {
128 None => Ok(Event::SystemClipboardFailure),
129 _ => Err("Malformed payload for the system clipboard failure Event"),
130 },
131 Some(ProtobufEventType::InputReceived) => match protobuf_event.payload {
132 None => Ok(Event::InputReceived),
133 _ => Err("Malformed payload for the input received Event"),
134 },
135 Some(ProtobufEventType::Visible) => match protobuf_event.payload {
136 Some(ProtobufEventPayload::VisiblePayload(is_visible)) => {
137 Ok(Event::Visible(is_visible))
138 },
139 _ => Err("Malformed payload for the visible Event"),
140 },
141 Some(ProtobufEventType::CustomMessage) => match protobuf_event.payload {
142 Some(ProtobufEventPayload::CustomMessagePayload(custom_message_payload)) => {
143 Ok(Event::CustomMessage(
144 custom_message_payload.message_name,
145 custom_message_payload.payload,
146 ))
147 },
148 _ => Err("Malformed payload for the custom message Event"),
149 },
150 Some(ProtobufEventType::FileSystemCreate) => match protobuf_event.payload {
151 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
152 let file_paths = file_list_payload
153 .paths
154 .iter()
155 .zip(file_list_payload.paths_metadata.iter())
156 .map(|(p, m)| (PathBuf::from(p), m.into()))
157 .collect();
158 Ok(Event::FileSystemCreate(file_paths))
159 },
160 _ => Err("Malformed payload for the file system create Event"),
161 },
162 Some(ProtobufEventType::FileSystemRead) => match protobuf_event.payload {
163 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
164 let file_paths = file_list_payload
165 .paths
166 .iter()
167 .zip(file_list_payload.paths_metadata.iter())
168 .map(|(p, m)| (PathBuf::from(p), m.into()))
169 .collect();
170 Ok(Event::FileSystemRead(file_paths))
171 },
172 _ => Err("Malformed payload for the file system read Event"),
173 },
174 Some(ProtobufEventType::FileSystemUpdate) => match protobuf_event.payload {
175 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
176 let file_paths = file_list_payload
177 .paths
178 .iter()
179 .zip(file_list_payload.paths_metadata.iter())
180 .map(|(p, m)| (PathBuf::from(p), m.into()))
181 .collect();
182 Ok(Event::FileSystemUpdate(file_paths))
183 },
184 _ => Err("Malformed payload for the file system update Event"),
185 },
186 Some(ProtobufEventType::FileSystemDelete) => match protobuf_event.payload {
187 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
188 let file_paths = file_list_payload
189 .paths
190 .iter()
191 .zip(file_list_payload.paths_metadata.iter())
192 .map(|(p, m)| (PathBuf::from(p), m.into()))
193 .collect();
194 Ok(Event::FileSystemDelete(file_paths))
195 },
196 _ => Err("Malformed payload for the file system delete Event"),
197 },
198 Some(ProtobufEventType::PermissionRequestResult) => match protobuf_event.payload {
199 Some(ProtobufEventPayload::PermissionRequestResultPayload(payload)) => {
200 if payload.granted {
201 Ok(Event::PermissionRequestResult(PermissionStatus::Granted))
202 } else {
203 Ok(Event::PermissionRequestResult(PermissionStatus::Denied))
204 }
205 },
206 _ => Err("Malformed payload for the file system delete Event"),
207 },
208 Some(ProtobufEventType::SessionUpdate) => match protobuf_event.payload {
209 Some(ProtobufEventPayload::SessionUpdatePayload(
210 protobuf_session_update_payload,
211 )) => {
212 let mut session_infos: Vec<SessionInfo> = vec![];
213 let mut resurrectable_sessions: Vec<(String, Duration)> = vec![];
214 for protobuf_session_info in protobuf_session_update_payload.session_manifests {
215 session_infos.push(SessionInfo::try_from(protobuf_session_info)?);
216 }
217 for protobuf_resurrectable_session in
218 protobuf_session_update_payload.resurrectable_sessions
219 {
220 resurrectable_sessions.push(protobuf_resurrectable_session.into());
221 }
222 Ok(Event::SessionUpdate(
223 session_infos,
224 resurrectable_sessions.into(),
225 ))
226 },
227 _ => Err("Malformed payload for the SessionUpdate Event"),
228 },
229 Some(ProtobufEventType::RunCommandResult) => match protobuf_event.payload {
230 Some(ProtobufEventPayload::RunCommandResultPayload(run_command_result_payload)) => {
231 Ok(Event::RunCommandResult(
232 run_command_result_payload.exit_code,
233 run_command_result_payload.stdout,
234 run_command_result_payload.stderr,
235 run_command_result_payload
236 .context
237 .into_iter()
238 .map(|c_i| (c_i.name, c_i.value))
239 .collect(),
240 ))
241 },
242 _ => Err("Malformed payload for the RunCommandResult Event"),
243 },
244 Some(ProtobufEventType::WebRequestResult) => match protobuf_event.payload {
245 Some(ProtobufEventPayload::WebRequestResultPayload(web_request_result_payload)) => {
246 Ok(Event::WebRequestResult(
247 web_request_result_payload.status as u16,
248 web_request_result_payload
249 .headers
250 .into_iter()
251 .map(|h| (h.name, h.value))
252 .collect(),
253 web_request_result_payload.body,
254 web_request_result_payload
255 .context
256 .into_iter()
257 .map(|c_i| (c_i.name, c_i.value))
258 .collect(),
259 ))
260 },
261 _ => Err("Malformed payload for the WebRequestResult Event"),
262 },
263 Some(ProtobufEventType::CommandPaneOpened) => match protobuf_event.payload {
264 Some(ProtobufEventPayload::CommandPaneOpenedPayload(
265 command_pane_opened_payload,
266 )) => Ok(Event::CommandPaneOpened(
267 command_pane_opened_payload.terminal_pane_id,
268 command_pane_opened_payload
269 .context
270 .into_iter()
271 .map(|c_i| (c_i.name, c_i.value))
272 .collect(),
273 )),
274 _ => Err("Malformed payload for the CommandPaneOpened Event"),
275 },
276 Some(ProtobufEventType::CommandPaneExited) => match protobuf_event.payload {
277 Some(ProtobufEventPayload::CommandPaneExitedPayload(
278 command_pane_exited_payload,
279 )) => Ok(Event::CommandPaneExited(
280 command_pane_exited_payload.terminal_pane_id,
281 command_pane_exited_payload.exit_code,
282 command_pane_exited_payload
283 .context
284 .into_iter()
285 .map(|c_i| (c_i.name, c_i.value))
286 .collect(),
287 )),
288 _ => Err("Malformed payload for the CommandPaneExited Event"),
289 },
290 Some(ProtobufEventType::PaneClosed) => match protobuf_event.payload {
291 Some(ProtobufEventPayload::PaneClosedPayload(pane_closed_payload)) => {
292 let pane_id = pane_closed_payload
293 .pane_id
294 .ok_or("Malformed payload for the PaneClosed Event")?;
295 Ok(Event::PaneClosed(PaneId::try_from(pane_id)?))
296 },
297 _ => Err("Malformed payload for the PaneClosed Event"),
298 },
299 Some(ProtobufEventType::EditPaneOpened) => match protobuf_event.payload {
300 Some(ProtobufEventPayload::EditPaneOpenedPayload(command_pane_opened_payload)) => {
301 Ok(Event::EditPaneOpened(
302 command_pane_opened_payload.terminal_pane_id,
303 command_pane_opened_payload
304 .context
305 .into_iter()
306 .map(|c_i| (c_i.name, c_i.value))
307 .collect(),
308 ))
309 },
310 _ => Err("Malformed payload for the EditPaneOpened Event"),
311 },
312 Some(ProtobufEventType::EditPaneExited) => match protobuf_event.payload {
313 Some(ProtobufEventPayload::EditPaneExitedPayload(command_pane_exited_payload)) => {
314 Ok(Event::EditPaneExited(
315 command_pane_exited_payload.terminal_pane_id,
316 command_pane_exited_payload.exit_code,
317 command_pane_exited_payload
318 .context
319 .into_iter()
320 .map(|c_i| (c_i.name, c_i.value))
321 .collect(),
322 ))
323 },
324 _ => Err("Malformed payload for the EditPaneExited Event"),
325 },
326 Some(ProtobufEventType::CommandPaneReRun) => match protobuf_event.payload {
327 Some(ProtobufEventPayload::CommandPaneRerunPayload(command_pane_rerun_payload)) => {
328 Ok(Event::CommandPaneReRun(
329 command_pane_rerun_payload.terminal_pane_id,
330 command_pane_rerun_payload
331 .context
332 .into_iter()
333 .map(|c_i| (c_i.name, c_i.value))
334 .collect(),
335 ))
336 },
337 _ => Err("Malformed payload for the CommandPaneReRun Event"),
338 },
339 Some(ProtobufEventType::FailedToWriteConfigToDisk) => match protobuf_event.payload {
340 Some(ProtobufEventPayload::FailedToWriteConfigToDiskPayload(
341 failed_to_write_configuration_payload,
342 )) => Ok(Event::FailedToWriteConfigToDisk(
343 failed_to_write_configuration_payload.file_path,
344 )),
345 _ => Err("Malformed payload for the FailedToWriteConfigToDisk Event"),
346 },
347 Some(ProtobufEventType::ListClients) => match protobuf_event.payload {
348 Some(ProtobufEventPayload::ListClientsPayload(mut list_clients_payload)) => {
349 Ok(Event::ListClients(
350 list_clients_payload
351 .client_info
352 .drain(..)
353 .filter_map(|c| c.try_into().ok())
354 .collect(),
355 ))
356 },
357 _ => Err("Malformed payload for the FailedToWriteConfigToDisk Event"),
358 },
359 Some(ProtobufEventType::HostFolderChanged) => match protobuf_event.payload {
360 Some(ProtobufEventPayload::HostFolderChangedPayload(
361 host_folder_changed_payload,
362 )) => Ok(Event::HostFolderChanged(PathBuf::from(
363 host_folder_changed_payload.new_host_folder_path,
364 ))),
365 _ => Err("Malformed payload for the HostFolderChanged Event"),
366 },
367 Some(ProtobufEventType::FailedToChangeHostFolder) => match protobuf_event.payload {
368 Some(ProtobufEventPayload::FailedToChangeHostFolderPayload(
369 failed_to_change_host_folder_payload,
370 )) => Ok(Event::FailedToChangeHostFolder(
371 failed_to_change_host_folder_payload.error_message,
372 )),
373 _ => Err("Malformed payload for the FailedToChangeHostFolder Event"),
374 },
375 Some(ProtobufEventType::PastedText) => match protobuf_event.payload {
376 Some(ProtobufEventPayload::PastedTextPayload(pasted_text_payload)) => {
377 Ok(Event::PastedText(pasted_text_payload.pasted_text))
378 },
379 _ => Err("Malformed payload for the PastedText Event"),
380 },
381 Some(ProtobufEventType::ConfigWasWrittenToDisk) => match protobuf_event.payload {
382 None => Ok(Event::ConfigWasWrittenToDisk),
383 _ => Err("Malformed payload for the ConfigWasWrittenToDisk Event"),
384 },
385 Some(ProtobufEventType::WebServerStatus) => match protobuf_event.payload {
386 Some(ProtobufEventPayload::WebServerStatusPayload(web_server_status)) => {
387 Ok(Event::WebServerStatus(web_server_status.try_into()?))
388 },
389 _ => Err("Malformed payload for the WebServerStatus Event"),
390 },
391 Some(ProtobufEventType::BeforeClose) => match protobuf_event.payload {
392 None => Ok(Event::BeforeClose),
393 _ => Err("Malformed payload for the BeforeClose Event"),
394 },
395 Some(ProtobufEventType::FailedToStartWebServer) => match protobuf_event.payload {
396 Some(ProtobufEventPayload::FailedToStartWebServerPayload(
397 failed_to_start_web_server_payload,
398 )) => Ok(Event::FailedToStartWebServer(
399 failed_to_start_web_server_payload.error,
400 )),
401 _ => Err("Malformed payload for the FailedToStartWebServer Event"),
402 },
403 Some(ProtobufEventType::InterceptedKeyPress) => match protobuf_event.payload {
404 Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => {
405 Ok(Event::InterceptedKeyPress(protobuf_key.try_into()?))
406 },
407 _ => Err("Malformed payload for the InterceptedKeyPress Event"),
408 },
409 Some(ProtobufEventType::PaneRenderReport) => match protobuf_event.payload {
410 Some(ProtobufEventPayload::PaneRenderReportPayload(protobuf_payload)) => {
411 Ok(Event::PaneRenderReport(protobuf_payload.try_into()?))
412 },
413 _ => Err("Malformed payload for the PaneRenderReport Event"),
414 },
415 Some(ProtobufEventType::PaneRenderReportWithAnsi) => match protobuf_event.payload {
416 Some(ProtobufEventPayload::PaneRenderReportWithAnsiPayload(protobuf_payload)) => {
417 Ok(Event::PaneRenderReportWithAnsi(
418 protobuf_payload.try_into()?,
419 ))
420 },
421 _ => Err("Malformed payload for the PaneRenderReportWithAnsi Event"),
422 },
423 Some(ProtobufEventType::UserAction) => match protobuf_event.payload {
424 Some(ProtobufEventPayload::UserActionPayload(protobuf_payload)) => {
425 let action: Action = protobuf_payload
426 .action
427 .ok_or("Missing action in UserAction payload")?
428 .try_into()
429 .map_err(|_| "Failed to convert Action in UserAction payload")?;
430 let client_id = protobuf_payload.client_id as u16;
431 let terminal_id = protobuf_payload.terminal_id;
432 let cli_client_id = protobuf_payload.cli_client_id.map(|id| id as u16);
433 Ok(Event::UserAction(
434 action,
435 client_id,
436 terminal_id,
437 cli_client_id,
438 ))
439 },
440 _ => Err("Malformed payload for the UserAction Event"),
441 },
442 Some(ProtobufEventType::ActionComplete) => match protobuf_event.payload {
443 Some(ProtobufEventPayload::ActionCompletePayload(protobuf_payload)) => {
444 let action: Action = protobuf_payload
445 .action
446 .ok_or("Missing action in ActionComplete payload")?
447 .try_into()
448 .map_err(|_| "Failed to convert Action in ActionComplete payload")?;
449 let pane_id = protobuf_payload
450 .pane_id
451 .map(|id| id.try_into())
452 .transpose()
453 .map_err(|_| "Failed to convert PaneId in ActionComplete payload")?;
454 let context: BTreeMap<String, String> = protobuf_payload
455 .context
456 .into_iter()
457 .map(|item| (item.name, item.value))
458 .collect();
459 Ok(Event::ActionComplete(action, pane_id, context))
460 },
461 _ => Err("Malformed payload for the ActionComplete Event"),
462 },
463 Some(ProtobufEventType::CwdChanged) => match protobuf_event.payload {
464 Some(ProtobufEventPayload::CwdChangedPayload(protobuf_payload)) => {
465 let pane_id: PaneId = protobuf_payload
466 .pane_id
467 .ok_or("Missing pane_id in CwdChanged payload")?
468 .try_into()
469 .map_err(|_| "Failed to convert PaneId in CwdChanged payload")?;
470 let new_cwd = PathBuf::from(protobuf_payload.new_cwd);
471 let focused_client_ids: Vec<ClientId> = protobuf_payload
472 .focused_client_ids
473 .into_iter()
474 .map(|id| id as u16)
475 .collect();
476 Ok(Event::CwdChanged(pane_id, new_cwd, focused_client_ids))
477 },
478 _ => Err("Malformed payload for the CwdChanged Event"),
479 },
480 Some(ProtobufEventType::CommandChanged) => match protobuf_event.payload {
481 Some(ProtobufEventPayload::CommandChangedPayload(p)) => {
482 let pane_id: PaneId = p
483 .pane_id
484 .ok_or("Missing pane_id in CommandChanged payload")?
485 .try_into()
486 .map_err(|_| "Failed to convert PaneId in CommandChanged payload")?;
487 let focused_client_ids: Vec<ClientId> = p
488 .focused_client_ids
489 .into_iter()
490 .map(|id| id as u16)
491 .collect();
492 Ok(Event::CommandChanged(
493 pane_id,
494 p.command,
495 p.is_foreground,
496 focused_client_ids,
497 ))
498 },
499 _ => Err("Malformed payload for the CommandChanged Event"),
500 },
501 Some(ProtobufEventType::AvailableLayoutInfo) => match protobuf_event.payload {
502 Some(ProtobufEventPayload::AvailableLayoutInfoPayload(
503 available_layout_info_payload,
504 )) => {
505 let mut available_layouts: Vec<LayoutInfo> = vec![];
506 let mut layouts_with_errors: Vec<crate::data::LayoutWithError> = vec![];
507
508 for protobuf_layout_info in available_layout_info_payload.available_layouts {
509 available_layouts.push(LayoutInfo::try_from(protobuf_layout_info)?);
510 }
511
512 for protobuf_error in available_layout_info_payload.layouts_with_errors {
513 layouts_with_errors
514 .push(crate::data::LayoutWithError::try_from(protobuf_error)?);
515 }
516
517 Ok(Event::AvailableLayoutInfo(
518 available_layouts,
519 layouts_with_errors,
520 ))
521 },
522 _ => Err("Malformed payload for the AvailableLayoutInfo Event"),
523 },
524 Some(ProtobufEventType::PluginConfigurationChanged) => match protobuf_event.payload {
525 Some(ProtobufEventPayload::PluginConfigurationChangedPayload(payload)) => {
526 let configuration = payload
527 .configuration
528 .into_iter()
529 .map(|item| (item.name, item.value))
530 .collect();
531 Ok(Event::PluginConfigurationChanged(configuration))
532 },
533 _ => Err("Malformed payload for PluginConfigurationChanged Event"),
534 },
535 Some(ProtobufEventType::HighlightClicked) => match protobuf_event.payload {
536 Some(ProtobufEventPayload::HighlightClickedPayload(p)) => {
537 let pane_id = p
538 .pane_id
539 .ok_or("Missing pane_id in HighlightClicked")?
540 .try_into()?;
541 let context = p
542 .context
543 .into_iter()
544 .map(|item| (item.name, item.value))
545 .collect();
546 Ok(Event::HighlightClicked {
547 pane_id,
548 pattern: p.pattern,
549 matched_string: p.matched_string,
550 context,
551 })
552 },
553 _ => Err("Malformed payload for HighlightClicked Event"),
554 },
555 Some(ProtobufEventType::InitialKeybinds) => match protobuf_event.payload {
556 Some(ProtobufEventPayload::InitialKeybindsPayload(p)) => {
557 let keybinds = p
558 .keybinds
559 .into_iter()
560 .filter_map(|imk| {
561 let mode: InputMode =
562 ProtobufInputMode::from_i32(imk.mode)?.try_into().ok()?;
563 let key_binds: Vec<(KeyWithModifier, Vec<Action>)> = imk
564 .key_bind
565 .into_iter()
566 .filter_map(|kb| {
567 let key: KeyWithModifier = kb.key?.try_into().ok()?;
568 let actions: Vec<Action> = kb
569 .action
570 .into_iter()
571 .filter_map(|a| a.try_into().ok())
572 .collect();
573 Some((key, actions))
574 })
575 .collect();
576 Some((mode, key_binds))
577 })
578 .collect();
579 Ok(Event::InitialKeybinds(keybinds))
580 },
581 _ => Err("Malformed payload for InitialKeybinds Event"),
582 },
583 Some(ProtobufEventType::HostTerminalThemeChanged) => match protobuf_event.payload {
584 Some(ProtobufEventPayload::HostTerminalThemeChangedPayload(p)) => {
585 let mode = ProtobufHostTerminalThemeIndication::from_i32(p.mode)
586 .ok_or("Unknown HostTerminalThemeIndication")?;
587 Ok(Event::HostTerminalThemeChanged(mode.into()))
588 },
589 _ => Err("Malformed payload for HostTerminalThemeChanged Event"),
590 },
591 None => Err("Unknown Protobuf Event"),
592 }
593 }
594}
595
596impl TryFrom<ProtobufClientInfo> for ClientInfo {
597 type Error = &'static str;
598 fn try_from(protobuf_client_info: ProtobufClientInfo) -> Result<Self, &'static str> {
599 Ok(ClientInfo::new(
600 protobuf_client_info.client_id as u16,
601 protobuf_client_info
602 .pane_id
603 .ok_or("No pane id found")?
604 .try_into()?,
605 protobuf_client_info.running_command,
606 protobuf_client_info.is_current_client,
607 ))
608 }
609}
610
611impl TryFrom<ClientInfo> for ProtobufClientInfo {
612 type Error = &'static str;
613 fn try_from(client_info: ClientInfo) -> Result<Self, &'static str> {
614 Ok(ProtobufClientInfo {
615 client_id: client_info.client_id as u32,
616 pane_id: Some(client_info.pane_id.try_into()?),
617 running_command: client_info.running_command,
618 is_current_client: client_info.is_current_client,
619 })
620 }
621}
622
623impl TryFrom<Event> for ProtobufEvent {
624 type Error = &'static str;
625 fn try_from(event: Event) -> Result<Self, &'static str> {
626 match event {
627 Event::ModeUpdate(mode_info) => {
628 let protobuf_mode_update_payload = mode_info.try_into()?;
629 Ok(ProtobufEvent {
630 name: ProtobufEventType::ModeUpdate as i32,
631 payload: Some(event::Payload::ModeUpdatePayload(
632 protobuf_mode_update_payload,
633 )),
634 })
635 },
636 Event::TabUpdate(tab_infos) => {
637 let mut protobuf_tab_infos = vec![];
638 for tab_info in tab_infos {
639 protobuf_tab_infos.push(tab_info.try_into()?);
640 }
641 let tab_update_payload = TabUpdatePayload {
642 tab_info: protobuf_tab_infos,
643 };
644 Ok(ProtobufEvent {
645 name: ProtobufEventType::TabUpdate as i32,
646 payload: Some(event::Payload::TabUpdatePayload(tab_update_payload)),
647 })
648 },
649 Event::PaneUpdate(pane_manifest) => {
650 let mut protobuf_pane_manifests = vec![];
651 for (tab_index, pane_infos) in pane_manifest.panes {
652 let mut protobuf_pane_infos = vec![];
653 for pane_info in pane_infos {
654 protobuf_pane_infos.push(pane_info.try_into()?);
655 }
656 protobuf_pane_manifests.push(ProtobufPaneManifest {
657 tab_index: tab_index as u32,
658 panes: protobuf_pane_infos,
659 });
660 }
661 Ok(ProtobufEvent {
662 name: ProtobufEventType::PaneUpdate as i32,
663 payload: Some(event::Payload::PaneUpdatePayload(PaneUpdatePayload {
664 pane_manifest: protobuf_pane_manifests,
665 })),
666 })
667 },
668 Event::Key(key) => Ok(ProtobufEvent {
669 name: ProtobufEventType::Key as i32,
670 payload: Some(event::Payload::KeyPayload(key.try_into()?)),
671 }),
672 Event::Mouse(mouse_event) => {
673 let protobuf_mouse_payload = mouse_event.try_into()?;
674 Ok(ProtobufEvent {
675 name: ProtobufEventType::Mouse as i32,
676 payload: Some(event::Payload::MouseEventPayload(protobuf_mouse_payload)),
677 })
678 },
679 Event::Timer(seconds) => Ok(ProtobufEvent {
680 name: ProtobufEventType::Timer as i32,
681 payload: Some(event::Payload::TimerPayload(seconds as f32)),
682 }),
683 Event::CopyToClipboard(clipboard_destination) => {
684 let protobuf_copy_destination: ProtobufCopyDestination =
685 clipboard_destination.try_into()?;
686 Ok(ProtobufEvent {
687 name: ProtobufEventType::CopyToClipboard as i32,
688 payload: Some(event::Payload::CopyToClipboardPayload(
689 protobuf_copy_destination as i32,
690 )),
691 })
692 },
693 Event::SystemClipboardFailure => Ok(ProtobufEvent {
694 name: ProtobufEventType::SystemClipboardFailure as i32,
695 payload: None,
696 }),
697 Event::InputReceived => Ok(ProtobufEvent {
698 name: ProtobufEventType::InputReceived as i32,
699 payload: None,
700 }),
701 Event::Visible(is_visible) => Ok(ProtobufEvent {
702 name: ProtobufEventType::Visible as i32,
703 payload: Some(event::Payload::VisiblePayload(is_visible)),
704 }),
705 Event::CustomMessage(message, payload) => Ok(ProtobufEvent {
706 name: ProtobufEventType::CustomMessage as i32,
707 payload: Some(event::Payload::CustomMessagePayload(CustomMessagePayload {
708 message_name: message,
709 payload,
710 })),
711 }),
712 Event::FileSystemCreate(event_paths) => {
713 let mut paths = vec![];
714 let mut paths_metadata = vec![];
715 for (path, path_metadata) in event_paths {
716 paths.push(path.display().to_string());
717 paths_metadata.push(path_metadata.into());
718 }
719 let file_list_payload = FileListPayload {
720 paths,
721 paths_metadata,
722 };
723 Ok(ProtobufEvent {
724 name: ProtobufEventType::FileSystemCreate as i32,
725 payload: Some(event::Payload::FileListPayload(file_list_payload)),
726 })
727 },
728 Event::FileSystemRead(event_paths) => {
729 let mut paths = vec![];
730 let mut paths_metadata = vec![];
731 for (path, path_metadata) in event_paths {
732 paths.push(path.display().to_string());
733 paths_metadata.push(path_metadata.into());
734 }
735 let file_list_payload = FileListPayload {
736 paths,
737 paths_metadata,
738 };
739 Ok(ProtobufEvent {
740 name: ProtobufEventType::FileSystemRead as i32,
741 payload: Some(event::Payload::FileListPayload(file_list_payload)),
742 })
743 },
744 Event::FileSystemUpdate(event_paths) => {
745 let mut paths = vec![];
746 let mut paths_metadata = vec![];
747 for (path, path_metadata) in event_paths {
748 paths.push(path.display().to_string());
749 paths_metadata.push(path_metadata.into());
750 }
751 let file_list_payload = FileListPayload {
752 paths,
753 paths_metadata,
754 };
755 Ok(ProtobufEvent {
756 name: ProtobufEventType::FileSystemUpdate as i32,
757 payload: Some(event::Payload::FileListPayload(file_list_payload)),
758 })
759 },
760 Event::FileSystemDelete(event_paths) => {
761 let mut paths = vec![];
762 let mut paths_metadata = vec![];
763 for (path, path_metadata) in event_paths {
764 paths.push(path.display().to_string());
765 paths_metadata.push(path_metadata.into());
766 }
767 let file_list_payload = FileListPayload {
768 paths,
769 paths_metadata,
770 };
771 Ok(ProtobufEvent {
772 name: ProtobufEventType::FileSystemDelete as i32,
773 payload: Some(event::Payload::FileListPayload(file_list_payload)),
774 })
775 },
776 Event::PermissionRequestResult(permission_status) => {
777 let granted = match permission_status {
778 PermissionStatus::Granted => true,
779 PermissionStatus::Denied => false,
780 };
781 Ok(ProtobufEvent {
782 name: ProtobufEventType::PermissionRequestResult as i32,
783 payload: Some(event::Payload::PermissionRequestResultPayload(
784 PermissionRequestResultPayload { granted },
785 )),
786 })
787 },
788 Event::SessionUpdate(session_infos, resurrectable_sessions) => {
789 let mut protobuf_session_manifests = vec![];
790 for session_info in session_infos {
791 protobuf_session_manifests.push(session_info.try_into()?);
792 }
793 let mut protobuf_resurrectable_sessions = vec![];
794 for resurrectable_session in resurrectable_sessions {
795 protobuf_resurrectable_sessions.push(resurrectable_session.into());
796 }
797 let session_update_payload = SessionUpdatePayload {
798 session_manifests: protobuf_session_manifests,
799 resurrectable_sessions: protobuf_resurrectable_sessions,
800 };
801 Ok(ProtobufEvent {
802 name: ProtobufEventType::SessionUpdate as i32,
803 payload: Some(event::Payload::SessionUpdatePayload(session_update_payload)),
804 })
805 },
806 Event::RunCommandResult(exit_code, stdout, stderr, context) => {
807 let run_command_result_payload = RunCommandResultPayload {
808 exit_code,
809 stdout,
810 stderr,
811 context: context
812 .into_iter()
813 .map(|(name, value)| ContextItem { name, value })
814 .collect(),
815 };
816 Ok(ProtobufEvent {
817 name: ProtobufEventType::RunCommandResult as i32,
818 payload: Some(event::Payload::RunCommandResultPayload(
819 run_command_result_payload,
820 )),
821 })
822 },
823 Event::WebRequestResult(status, headers, body, context) => {
824 let web_request_result_payload = WebRequestResultPayload {
825 status: status as i32,
826 headers: headers
827 .into_iter()
828 .map(|(name, value)| Header { name, value })
829 .collect(),
830 body,
831 context: context
832 .into_iter()
833 .map(|(name, value)| ContextItem { name, value })
834 .collect(),
835 };
836 Ok(ProtobufEvent {
837 name: ProtobufEventType::WebRequestResult as i32,
838 payload: Some(event::Payload::WebRequestResultPayload(
839 web_request_result_payload,
840 )),
841 })
842 },
843 Event::CommandPaneOpened(terminal_pane_id, context) => {
844 let command_pane_opened_payload = CommandPaneOpenedPayload {
845 terminal_pane_id,
846 context: context
847 .into_iter()
848 .map(|(name, value)| ContextItem { name, value })
849 .collect(),
850 };
851 Ok(ProtobufEvent {
852 name: ProtobufEventType::CommandPaneOpened as i32,
853 payload: Some(event::Payload::CommandPaneOpenedPayload(
854 command_pane_opened_payload,
855 )),
856 })
857 },
858 Event::CommandPaneExited(terminal_pane_id, exit_code, context) => {
859 let command_pane_exited_payload = CommandPaneExitedPayload {
860 terminal_pane_id,
861 exit_code,
862 context: context
863 .into_iter()
864 .map(|(name, value)| ContextItem { name, value })
865 .collect(),
866 };
867 Ok(ProtobufEvent {
868 name: ProtobufEventType::CommandPaneExited as i32,
869 payload: Some(event::Payload::CommandPaneExitedPayload(
870 command_pane_exited_payload,
871 )),
872 })
873 },
874 Event::PaneClosed(pane_id) => Ok(ProtobufEvent {
875 name: ProtobufEventType::PaneClosed as i32,
876 payload: Some(event::Payload::PaneClosedPayload(PaneClosedPayload {
877 pane_id: Some(pane_id.try_into()?),
878 })),
879 }),
880 Event::EditPaneOpened(terminal_pane_id, context) => {
881 let command_pane_opened_payload = EditPaneOpenedPayload {
882 terminal_pane_id,
883 context: context
884 .into_iter()
885 .map(|(name, value)| ContextItem { name, value })
886 .collect(),
887 };
888 Ok(ProtobufEvent {
889 name: ProtobufEventType::EditPaneOpened as i32,
890 payload: Some(event::Payload::EditPaneOpenedPayload(
891 command_pane_opened_payload,
892 )),
893 })
894 },
895 Event::EditPaneExited(terminal_pane_id, exit_code, context) => {
896 let command_pane_exited_payload = EditPaneExitedPayload {
897 terminal_pane_id,
898 exit_code,
899 context: context
900 .into_iter()
901 .map(|(name, value)| ContextItem { name, value })
902 .collect(),
903 };
904 Ok(ProtobufEvent {
905 name: ProtobufEventType::EditPaneExited as i32,
906 payload: Some(event::Payload::EditPaneExitedPayload(
907 command_pane_exited_payload,
908 )),
909 })
910 },
911 Event::CommandPaneReRun(terminal_pane_id, context) => {
912 let command_pane_rerun_payload = CommandPaneReRunPayload {
913 terminal_pane_id,
914 context: context
915 .into_iter()
916 .map(|(name, value)| ContextItem { name, value })
917 .collect(),
918 };
919 Ok(ProtobufEvent {
920 name: ProtobufEventType::CommandPaneReRun as i32,
921 payload: Some(event::Payload::CommandPaneRerunPayload(
922 command_pane_rerun_payload,
923 )),
924 })
925 },
926 Event::FailedToWriteConfigToDisk(file_path) => Ok(ProtobufEvent {
927 name: ProtobufEventType::FailedToWriteConfigToDisk as i32,
928 payload: Some(event::Payload::FailedToWriteConfigToDiskPayload(
929 FailedToWriteConfigToDiskPayload { file_path },
930 )),
931 }),
932 Event::ListClients(mut client_info_list) => Ok(ProtobufEvent {
933 name: ProtobufEventType::ListClients as i32,
934 payload: Some(event::Payload::ListClientsPayload(ListClientsPayload {
935 client_info: client_info_list
936 .drain(..)
937 .filter_map(|c| c.try_into().ok())
938 .collect(),
939 })),
940 }),
941 Event::HostFolderChanged(new_host_folder_path) => Ok(ProtobufEvent {
942 name: ProtobufEventType::HostFolderChanged as i32,
943 payload: Some(event::Payload::HostFolderChangedPayload(
944 HostFolderChangedPayload {
945 new_host_folder_path: new_host_folder_path.display().to_string(),
946 },
947 )),
948 }),
949 Event::FailedToChangeHostFolder(error_message) => Ok(ProtobufEvent {
950 name: ProtobufEventType::FailedToChangeHostFolder as i32,
951 payload: Some(event::Payload::FailedToChangeHostFolderPayload(
952 FailedToChangeHostFolderPayload { error_message },
953 )),
954 }),
955 Event::PastedText(pasted_text) => Ok(ProtobufEvent {
956 name: ProtobufEventType::PastedText as i32,
957 payload: Some(event::Payload::PastedTextPayload(PastedTextPayload {
958 pasted_text,
959 })),
960 }),
961 Event::ConfigWasWrittenToDisk => Ok(ProtobufEvent {
962 name: ProtobufEventType::ConfigWasWrittenToDisk as i32,
963 payload: None,
964 }),
965 Event::WebServerStatus(web_server_status) => Ok(ProtobufEvent {
966 name: ProtobufEventType::WebServerStatus as i32,
967 payload: Some(event::Payload::WebServerStatusPayload(
968 ProtobufWebServerStatusPayload::try_from(web_server_status)?,
969 )),
970 }),
971 Event::BeforeClose => Ok(ProtobufEvent {
972 name: ProtobufEventType::BeforeClose as i32,
973 payload: None,
974 }),
975 Event::FailedToStartWebServer(error) => Ok(ProtobufEvent {
976 name: ProtobufEventType::FailedToStartWebServer as i32,
977 payload: Some(event::Payload::FailedToStartWebServerPayload(
978 FailedToStartWebServerPayload { error },
979 )),
980 }),
981 Event::InterceptedKeyPress(key) => Ok(ProtobufEvent {
982 name: ProtobufEventType::InterceptedKeyPress as i32,
983 payload: Some(event::Payload::KeyPayload(key.try_into()?)),
984 }),
985 Event::PaneRenderReport(pane_contents_map) => Ok(ProtobufEvent {
986 name: ProtobufEventType::PaneRenderReport as i32,
987 payload: Some(event::Payload::PaneRenderReportPayload(
988 pane_contents_map.try_into()?,
989 )),
990 }),
991 Event::PaneRenderReportWithAnsi(pane_contents_map) => Ok(ProtobufEvent {
992 name: ProtobufEventType::PaneRenderReportWithAnsi as i32,
993 payload: Some(event::Payload::PaneRenderReportWithAnsiPayload(
994 pane_contents_map.try_into()?,
995 )),
996 }),
997 Event::UserAction(action, client_id, terminal_id, cli_client_id) => {
998 let protobuf_action: ProtobufAction = action
999 .try_into()
1000 .map_err(|_| "Failed to convert Action to protobuf")?;
1001 let protobuf_payload = ProtobufUserActionPayload {
1002 action: Some(protobuf_action),
1003 client_id: client_id as u32,
1004 terminal_id,
1005 cli_client_id: cli_client_id.map(|id| id as u32),
1006 };
1007 Ok(ProtobufEvent {
1008 name: ProtobufEventType::UserAction as i32,
1009 payload: Some(event::Payload::UserActionPayload(protobuf_payload)),
1010 })
1011 },
1012 Event::ActionComplete(action, pane_id, context) => {
1013 let protobuf_action = action.try_into()?;
1014 let protobuf_pane_id = pane_id.map(|id| id.try_into()).transpose()?;
1015 let context_items: Vec<ProtobufContextItem> = context
1016 .into_iter()
1017 .map(|(name, value)| ProtobufContextItem { name, value })
1018 .collect();
1019 let action_complete_payload = ProtobufActionCompletePayload {
1020 action: Some(protobuf_action),
1021 pane_id: protobuf_pane_id,
1022 context: context_items,
1023 };
1024 Ok(ProtobufEvent {
1025 name: ProtobufEventType::ActionComplete as i32,
1026 payload: Some(event::Payload::ActionCompletePayload(
1027 action_complete_payload,
1028 )),
1029 })
1030 },
1031 Event::CwdChanged(pane_id, new_cwd, focused_client_ids) => {
1032 let protobuf_pane_id: ProtobufPaneId = pane_id.try_into()?;
1033 let new_cwd_string = new_cwd
1034 .to_str()
1035 .ok_or("Failed to convert PathBuf to string")?
1036 .to_string();
1037 let focused_client_ids_u32: Vec<u32> =
1038 focused_client_ids.into_iter().map(|id| id as u32).collect();
1039 let cwd_changed_payload = ProtobufCwdChangedPayload {
1040 pane_id: Some(protobuf_pane_id),
1041 new_cwd: new_cwd_string,
1042 focused_client_ids: focused_client_ids_u32,
1043 };
1044 Ok(ProtobufEvent {
1045 name: ProtobufEventType::CwdChanged as i32,
1046 payload: Some(event::Payload::CwdChangedPayload(cwd_changed_payload)),
1047 })
1048 },
1049 Event::CommandChanged(pane_id, command, is_foreground, focused_client_ids) => {
1050 let protobuf_pane_id: ProtobufPaneId = pane_id.try_into()?;
1051 let focused_client_ids_u32: Vec<u32> =
1052 focused_client_ids.into_iter().map(|id| id as u32).collect();
1053 let payload = ProtobufCommandChangedPayload {
1054 pane_id: Some(protobuf_pane_id),
1055 command,
1056 is_foreground,
1057 focused_client_ids: focused_client_ids_u32,
1058 };
1059 Ok(ProtobufEvent {
1060 name: ProtobufEventType::CommandChanged as i32,
1061 payload: Some(event::Payload::CommandChangedPayload(payload)),
1062 })
1063 },
1064 Event::AvailableLayoutInfo(available_layouts, layouts_with_errors) => {
1065 let mut protobuf_available_layouts = vec![];
1066 let mut protobuf_layouts_with_errors = vec![];
1067
1068 for layout_info in available_layouts {
1069 protobuf_available_layouts.push(layout_info.try_into()?);
1070 }
1071
1072 for layout_error in layouts_with_errors {
1073 protobuf_layouts_with_errors.push(layout_error.try_into()?);
1074 }
1075
1076 let available_layout_info_payload = ProtobufAvailableLayoutInfoPayload {
1077 available_layouts: protobuf_available_layouts,
1078 layouts_with_errors: protobuf_layouts_with_errors,
1079 };
1080
1081 Ok(ProtobufEvent {
1082 name: ProtobufEventType::AvailableLayoutInfo as i32,
1083 payload: Some(event::Payload::AvailableLayoutInfoPayload(
1084 available_layout_info_payload,
1085 )),
1086 })
1087 },
1088 Event::PluginConfigurationChanged(configuration) => {
1089 let configuration_items: Vec<ProtobufContextItem> = configuration
1090 .into_iter()
1091 .map(|(name, value)| ProtobufContextItem { name, value })
1092 .collect();
1093
1094 let payload = ProtobufPluginConfigurationChangedPayload {
1095 configuration: configuration_items,
1096 };
1097
1098 Ok(ProtobufEvent {
1099 name: ProtobufEventType::PluginConfigurationChanged as i32,
1100 payload: Some(event::Payload::PluginConfigurationChangedPayload(payload)),
1101 })
1102 },
1103 Event::HighlightClicked {
1104 pane_id,
1105 pattern,
1106 matched_string,
1107 context,
1108 } => Ok(ProtobufEvent {
1109 name: ProtobufEventType::HighlightClicked as i32,
1110 payload: Some(event::Payload::HighlightClickedPayload(
1111 HighlightClickedPayload {
1112 pane_id: pane_id.try_into().ok(),
1113 pattern,
1114 matched_string,
1115 context: context
1116 .into_iter()
1117 .map(|(name, value)| ProtobufContextItem { name, value })
1118 .collect(),
1119 },
1120 )),
1121 }),
1122 Event::HostTerminalThemeChanged(mode) => {
1123 let proto_mode: ProtobufHostTerminalThemeIndication = mode.into();
1124 let payload = ProtobufHostTerminalThemeChangedPayload {
1125 mode: proto_mode as i32,
1126 };
1127 Ok(ProtobufEvent {
1128 name: ProtobufEventType::HostTerminalThemeChanged as i32,
1129 payload: Some(event::Payload::HostTerminalThemeChangedPayload(payload)),
1130 })
1131 },
1132 Event::InitialKeybinds(keybinds) => {
1133 let mut protobuf_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
1134 for (input_mode, input_mode_keybinds) in keybinds {
1135 let mode: ProtobufInputMode = input_mode.try_into()?;
1136 let mut key_binds: Vec<ProtobufKeyBind> = vec![];
1137 for (key, actions) in input_mode_keybinds {
1138 let protobuf_key: ProtobufKey = key.try_into()?;
1139 let mut protobuf_actions: Vec<ProtobufAction> = vec![];
1140 for action in actions {
1141 if let Ok(protobuf_action) = action.try_into() {
1142 protobuf_actions.push(protobuf_action);
1143 }
1144 }
1145 key_binds.push(ProtobufKeyBind {
1146 key: Some(protobuf_key),
1147 action: protobuf_actions,
1148 });
1149 }
1150 protobuf_keybinds.push(ProtobufInputModeKeybinds {
1151 mode: mode as i32,
1152 key_bind: key_binds,
1153 });
1154 }
1155 Ok(ProtobufEvent {
1156 name: ProtobufEventType::InitialKeybinds as i32,
1157 payload: Some(event::Payload::InitialKeybindsPayload(
1158 InitialKeybindsPayload {
1159 keybinds: protobuf_keybinds,
1160 },
1161 )),
1162 })
1163 },
1164 }
1165 }
1166}
1167
1168impl TryFrom<SessionInfo> for ProtobufSessionManifest {
1169 type Error = &'static str;
1170 fn try_from(session_info: SessionInfo) -> Result<Self, &'static str> {
1171 let mut protobuf_pane_manifests = vec![];
1172 for (tab_index, pane_infos) in session_info.panes.panes {
1173 let mut protobuf_pane_infos = vec![];
1174 for pane_info in pane_infos {
1175 protobuf_pane_infos.push(pane_info.try_into()?);
1176 }
1177 protobuf_pane_manifests.push(ProtobufPaneManifest {
1178 tab_index: tab_index as u32,
1179 panes: protobuf_pane_infos,
1180 });
1181 }
1182 Ok(ProtobufSessionManifest {
1183 name: session_info.name,
1184 panes: protobuf_pane_manifests,
1185 tabs: session_info
1186 .tabs
1187 .iter()
1188 .filter_map(|t| t.clone().try_into().ok())
1189 .collect(),
1190 connected_clients: session_info.connected_clients as u32,
1191 is_current_session: session_info.is_current_session,
1192 available_layouts: session_info
1193 .available_layouts
1194 .into_iter()
1195 .filter_map(|l| ProtobufLayoutInfo::try_from(l).ok())
1196 .collect(),
1197 plugins: session_info
1198 .plugins
1199 .into_iter()
1200 .map(|p| ProtobufPluginInfo::from(p))
1201 .collect(),
1202 web_clients_allowed: session_info.web_clients_allowed,
1203 web_client_count: session_info.web_client_count as u32,
1204 tab_history: session_info
1205 .tab_history
1206 .into_iter()
1207 .map(|t| ProtobufClientTabHistory::from(t))
1208 .collect(),
1209 pane_history: session_info
1210 .pane_history
1211 .into_iter()
1212 .map(|p| ProtobufClientPaneHistory::from(p))
1213 .collect(),
1214 creation_time: session_info.creation_time.as_secs(),
1215 })
1216 }
1217}
1218
1219impl From<(u16, Vec<usize>)> for ProtobufClientTabHistory {
1220 fn from((client_id, tab_history): (u16, Vec<usize>)) -> ProtobufClientTabHistory {
1221 ProtobufClientTabHistory {
1222 client_id: client_id as u32,
1223 tab_history: tab_history.into_iter().map(|t| t as u32).collect(),
1224 }
1225 }
1226}
1227
1228impl From<(u16, Vec<PaneId>)> for ProtobufClientPaneHistory {
1229 fn from((client_id, pane_history): (u16, Vec<PaneId>)) -> ProtobufClientPaneHistory {
1230 ProtobufClientPaneHistory {
1231 client_id: client_id as u32,
1232 pane_history: pane_history
1233 .into_iter()
1234 .filter_map(|p| p.try_into().ok())
1235 .collect(),
1236 }
1237 }
1238}
1239impl From<(u32, PluginInfo)> for ProtobufPluginInfo {
1240 fn from((plugin_id, plugin_info): (u32, PluginInfo)) -> ProtobufPluginInfo {
1241 ProtobufPluginInfo {
1242 plugin_id,
1243 plugin_url: plugin_info.location,
1244 plugin_config: plugin_info
1245 .configuration
1246 .into_iter()
1247 .map(|(name, value)| ContextItem { name, value })
1248 .collect(),
1249 }
1250 }
1251}
1252
1253impl TryFrom<ProtobufSessionManifest> for SessionInfo {
1254 type Error = &'static str;
1255 fn try_from(protobuf_session_manifest: ProtobufSessionManifest) -> Result<Self, &'static str> {
1256 let mut pane_manifest: HashMap<usize, Vec<PaneInfo>> = HashMap::new();
1257 for protobuf_pane_manifest in protobuf_session_manifest.panes {
1258 let tab_index = protobuf_pane_manifest.tab_index as usize;
1259 let mut panes = vec![];
1260 for protobuf_pane_info in protobuf_pane_manifest.panes {
1261 panes.push(protobuf_pane_info.try_into()?);
1262 }
1263 if pane_manifest.contains_key(&tab_index) {
1264 return Err("Duplicate tab definition in pane manifest");
1265 }
1266 pane_manifest.insert(tab_index, panes);
1267 }
1268 let panes = PaneManifest {
1269 panes: pane_manifest,
1270 };
1271 let mut plugins = BTreeMap::new();
1272 for plugin_info in protobuf_session_manifest.plugins.into_iter() {
1273 let mut configuration = BTreeMap::new();
1274 for context_item in plugin_info.plugin_config.into_iter() {
1275 configuration.insert(context_item.name, context_item.value);
1276 }
1277 plugins.insert(
1278 plugin_info.plugin_id,
1279 PluginInfo {
1280 location: plugin_info.plugin_url,
1281 configuration,
1282 },
1283 );
1284 }
1285 let mut tab_history = BTreeMap::new();
1286 for client_tab_history in protobuf_session_manifest.tab_history.into_iter() {
1287 let client_id = client_tab_history.client_id;
1288 let tab_history_for_client = client_tab_history
1289 .tab_history
1290 .iter()
1291 .map(|t| *t as usize)
1292 .collect();
1293 tab_history.insert(client_id as u16, tab_history_for_client);
1294 }
1295 let mut pane_history = BTreeMap::new();
1296 for client_pane_history in protobuf_session_manifest.pane_history.into_iter() {
1297 let client_id = client_pane_history.client_id;
1298 let pane_history_for_client = client_pane_history
1299 .pane_history
1300 .into_iter()
1301 .filter_map(|p| p.try_into().ok())
1302 .collect();
1303 pane_history.insert(client_id as u16, pane_history_for_client);
1304 }
1305 Ok(SessionInfo {
1306 name: protobuf_session_manifest.name,
1307 tabs: protobuf_session_manifest
1308 .tabs
1309 .iter()
1310 .filter_map(|t| t.clone().try_into().ok())
1311 .collect(),
1312 panes,
1313 connected_clients: protobuf_session_manifest.connected_clients as usize,
1314 is_current_session: protobuf_session_manifest.is_current_session,
1315 available_layouts: protobuf_session_manifest
1316 .available_layouts
1317 .into_iter()
1318 .filter_map(|l| LayoutInfo::try_from(l).ok())
1319 .collect(),
1320 plugins,
1321 web_clients_allowed: protobuf_session_manifest.web_clients_allowed,
1322 web_client_count: protobuf_session_manifest.web_client_count as usize,
1323 tab_history,
1324 pane_history,
1325 creation_time: Duration::from_secs(protobuf_session_manifest.creation_time),
1326 })
1327 }
1328}
1329
1330impl TryFrom<LayoutInfo> for ProtobufLayoutInfo {
1331 type Error = &'static str;
1332 fn try_from(layout_info: LayoutInfo) -> Result<Self, &'static str> {
1333 match layout_info {
1334 LayoutInfo::File(name, layout_metadata) => Ok(ProtobufLayoutInfo {
1335 source: "file".to_owned(),
1336 name,
1337 layout_metadata: Some(layout_metadata.try_into()?),
1338 }),
1339 LayoutInfo::BuiltIn(name) => Ok(ProtobufLayoutInfo {
1340 source: "built-in".to_owned(),
1341 name,
1342 layout_metadata: None,
1343 }),
1344 LayoutInfo::Url(name) => Ok(ProtobufLayoutInfo {
1345 source: "url".to_owned(),
1346 name,
1347 layout_metadata: None,
1348 }),
1349 LayoutInfo::Stringified(stringified_layout) => Ok(ProtobufLayoutInfo {
1350 source: "stringified".to_owned(),
1351 name: stringified_layout.clone(),
1352 layout_metadata: None,
1353 }),
1354 }
1355 }
1356}
1357
1358impl TryFrom<ProtobufLayoutInfo> for LayoutInfo {
1359 type Error = &'static str;
1360 fn try_from(protobuf_layout_info: ProtobufLayoutInfo) -> Result<Self, &'static str> {
1361 match protobuf_layout_info.source.as_str() {
1362 "file" => {
1363 let layout_metadata = protobuf_layout_info
1364 .layout_metadata
1365 .map(|m| m.try_into())
1366 .transpose()?
1367 .unwrap_or_default();
1368 Ok(LayoutInfo::File(protobuf_layout_info.name, layout_metadata))
1369 },
1370 "built-in" => Ok(LayoutInfo::BuiltIn(protobuf_layout_info.name)),
1371 "url" => Ok(LayoutInfo::Url(protobuf_layout_info.name)),
1372 "stringified" => Ok(LayoutInfo::Stringified(protobuf_layout_info.name)),
1373 _ => Err("Unknown source for layout"),
1374 }
1375 }
1376}
1377
1378impl TryFrom<ProtobufLayoutMetadata> for LayoutMetadata {
1379 type Error = &'static str;
1380 fn try_from(protobuf_metadata: ProtobufLayoutMetadata) -> Result<Self, &'static str> {
1381 let tabs = protobuf_metadata
1382 .tabs
1383 .into_iter()
1384 .map(|t| t.try_into())
1385 .collect::<Result<Vec<_>, _>>()?;
1386 Ok(LayoutMetadata {
1387 tabs,
1388 creation_time: protobuf_metadata.creation_time,
1389 update_time: protobuf_metadata.update_time,
1390 })
1391 }
1392}
1393
1394impl TryFrom<LayoutMetadata> for ProtobufLayoutMetadata {
1395 type Error = &'static str;
1396 fn try_from(metadata: LayoutMetadata) -> Result<Self, &'static str> {
1397 let tabs = metadata
1398 .tabs
1399 .into_iter()
1400 .map(|t| t.try_into())
1401 .collect::<Result<Vec<_>, _>>()?;
1402 Ok(ProtobufLayoutMetadata {
1403 tabs,
1404 creation_time: metadata.creation_time,
1405 update_time: metadata.update_time,
1406 })
1407 }
1408}
1409
1410impl TryFrom<ProtobufTabMetadata> for TabMetadata {
1411 type Error = &'static str;
1412 fn try_from(protobuf_metadata: ProtobufTabMetadata) -> Result<Self, &'static str> {
1413 let panes = protobuf_metadata
1414 .pane_metadata
1415 .into_iter()
1416 .map(|p| p.try_into())
1417 .collect::<Result<Vec<_>, _>>()?;
1418 Ok(TabMetadata {
1419 panes,
1420 name: protobuf_metadata.name,
1421 })
1422 }
1423}
1424
1425impl TryFrom<TabMetadata> for ProtobufTabMetadata {
1426 type Error = &'static str;
1427 fn try_from(metadata: TabMetadata) -> Result<Self, &'static str> {
1428 let pane_metadata = metadata
1429 .panes
1430 .into_iter()
1431 .map(|p| p.try_into())
1432 .collect::<Result<Vec<_>, _>>()?;
1433 Ok(ProtobufTabMetadata {
1434 pane_metadata,
1435 name: metadata.name,
1436 })
1437 }
1438}
1439
1440impl TryFrom<ProtobufPaneMetadata> for PaneMetadata {
1441 type Error = &'static str;
1442 fn try_from(protobuf_metadata: ProtobufPaneMetadata) -> Result<Self, &'static str> {
1443 Ok(PaneMetadata {
1444 name: protobuf_metadata.name,
1445 is_plugin: protobuf_metadata.is_plugin,
1446 is_builtin_plugin: protobuf_metadata.is_builtin_plugin,
1447 })
1448 }
1449}
1450
1451impl TryFrom<PaneMetadata> for ProtobufPaneMetadata {
1452 type Error = &'static str;
1453 fn try_from(metadata: PaneMetadata) -> Result<Self, &'static str> {
1454 Ok(ProtobufPaneMetadata {
1455 name: metadata.name,
1456 is_plugin: metadata.is_plugin,
1457 is_builtin_plugin: metadata.is_builtin_plugin,
1458 })
1459 }
1460}
1461
1462impl TryFrom<ProtobufLayoutWithError> for crate::data::LayoutWithError {
1464 type Error = &'static str;
1465 fn try_from(protobuf: ProtobufLayoutWithError) -> Result<Self, Self::Error> {
1466 Ok(crate::data::LayoutWithError {
1467 layout_name: protobuf.layout_name,
1468 error: protobuf.error.ok_or("Missing error field")?.try_into()?,
1469 })
1470 }
1471}
1472
1473impl TryFrom<crate::data::LayoutWithError> for ProtobufLayoutWithError {
1474 type Error = &'static str;
1475 fn try_from(layout_error: crate::data::LayoutWithError) -> Result<Self, Self::Error> {
1476 Ok(ProtobufLayoutWithError {
1477 layout_name: layout_error.layout_name,
1478 error: Some(layout_error.error.try_into()?),
1479 })
1480 }
1481}
1482
1483impl TryFrom<ProtobufLayoutParsingError> for crate::data::LayoutParsingError {
1485 type Error = &'static str;
1486 fn try_from(protobuf: ProtobufLayoutParsingError) -> Result<Self, Self::Error> {
1487 match protobuf.error_type.ok_or("Missing error_type")? {
1488 ProtobufLayoutParsingErrorType::KdlError(kdl_variant) => {
1489 Ok(crate::data::LayoutParsingError::KdlError {
1490 kdl_error: kdl_variant
1491 .kdl_error
1492 .ok_or("Missing kdl_error")?
1493 .try_into()?,
1494 file_name: kdl_variant.file_name,
1495 source_code: kdl_variant.source_code,
1496 })
1497 },
1498 ProtobufLayoutParsingErrorType::SyntaxError(_) => {
1499 Ok(crate::data::LayoutParsingError::SyntaxError)
1500 },
1501 }
1502 }
1503}
1504
1505impl TryFrom<crate::data::LayoutParsingError> for ProtobufLayoutParsingError {
1506 type Error = &'static str;
1507 fn try_from(error: crate::data::LayoutParsingError) -> Result<Self, Self::Error> {
1508 let error_type = match error {
1509 crate::data::LayoutParsingError::KdlError {
1510 kdl_error,
1511 file_name,
1512 source_code,
1513 } => ProtobufLayoutParsingErrorType::KdlError(ProtobufKdlErrorVariant {
1514 kdl_error: Some(kdl_error.try_into()?),
1515 file_name,
1516 source_code,
1517 }),
1518 crate::data::LayoutParsingError::SyntaxError => {
1519 ProtobufLayoutParsingErrorType::SyntaxError(ProtobufSyntaxError {})
1520 },
1521 };
1522 Ok(ProtobufLayoutParsingError {
1523 error_type: Some(error_type),
1524 })
1525 }
1526}
1527
1528impl TryFrom<ProtobufKdlError> for crate::input::config::KdlError {
1530 type Error = &'static str;
1531 fn try_from(protobuf: ProtobufKdlError) -> Result<Self, Self::Error> {
1532 Ok(crate::input::config::KdlError {
1533 error_message: protobuf.error_message,
1534 src: None, offset: protobuf.offset.map(|o| o as usize),
1536 len: protobuf.len.map(|l| l as usize),
1537 help_message: protobuf.help_message,
1538 })
1539 }
1540}
1541
1542impl TryFrom<crate::input::config::KdlError> for ProtobufKdlError {
1543 type Error = &'static str;
1544 fn try_from(kdl: crate::input::config::KdlError) -> Result<Self, Self::Error> {
1545 Ok(ProtobufKdlError {
1546 error_message: kdl.error_message,
1547 offset: kdl.offset.map(|o| o as u64),
1549 len: kdl.len.map(|l| l as u64),
1550 help_message: kdl.help_message,
1551 })
1552 }
1553}
1554
1555impl TryFrom<CopyDestination> for ProtobufCopyDestination {
1556 type Error = &'static str;
1557 fn try_from(copy_destination: CopyDestination) -> Result<Self, &'static str> {
1558 match copy_destination {
1559 CopyDestination::Command => Ok(ProtobufCopyDestination::Command),
1560 CopyDestination::Primary => Ok(ProtobufCopyDestination::Primary),
1561 CopyDestination::System => Ok(ProtobufCopyDestination::System),
1562 }
1563 }
1564}
1565
1566impl TryFrom<ProtobufCopyDestination> for CopyDestination {
1567 type Error = &'static str;
1568 fn try_from(protobuf_copy_destination: ProtobufCopyDestination) -> Result<Self, &'static str> {
1569 match protobuf_copy_destination {
1570 ProtobufCopyDestination::Command => Ok(CopyDestination::Command),
1571 ProtobufCopyDestination::Primary => Ok(CopyDestination::Primary),
1572 ProtobufCopyDestination::System => Ok(CopyDestination::System),
1573 }
1574 }
1575}
1576
1577impl TryFrom<MouseEventPayload> for Mouse {
1578 type Error = &'static str;
1579 fn try_from(mouse_event_payload: MouseEventPayload) -> Result<Self, &'static str> {
1580 match MouseEventName::from_i32(mouse_event_payload.mouse_event_name) {
1581 Some(MouseEventName::MouseScrollUp) => match mouse_event_payload.mouse_event_payload {
1582 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
1583 Ok(Mouse::ScrollUp(line_count as usize))
1584 },
1585 _ => Err("Malformed payload for mouse scroll up"),
1586 },
1587 Some(MouseEventName::MouseScrollDown) => {
1588 match mouse_event_payload.mouse_event_payload {
1589 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
1590 Ok(Mouse::ScrollDown(line_count as usize))
1591 },
1592 _ => Err("Malformed payload for mouse scroll down"),
1593 }
1594 },
1595 Some(MouseEventName::MouseLeftClick) => match mouse_event_payload.mouse_event_payload {
1596 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1597 Mouse::LeftClick(position.line as isize, position.column as usize),
1598 ),
1599 _ => Err("Malformed payload for mouse left click"),
1600 },
1601 Some(MouseEventName::MouseRightClick) => {
1602 match mouse_event_payload.mouse_event_payload {
1603 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1604 Mouse::RightClick(position.line as isize, position.column as usize),
1605 ),
1606 _ => Err("Malformed payload for mouse right click"),
1607 }
1608 },
1609 Some(MouseEventName::MouseHold) => match mouse_event_payload.mouse_event_payload {
1610 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1611 Mouse::Hold(position.line as isize, position.column as usize),
1612 ),
1613 _ => Err("Malformed payload for mouse hold"),
1614 },
1615 Some(MouseEventName::MouseRelease) => match mouse_event_payload.mouse_event_payload {
1616 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1617 Mouse::Release(position.line as isize, position.column as usize),
1618 ),
1619 _ => Err("Malformed payload for mouse release"),
1620 },
1621 Some(MouseEventName::MouseHover) => match mouse_event_payload.mouse_event_payload {
1622 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1623 Mouse::Hover(position.line as isize, position.column as usize),
1624 ),
1625 _ => Err("Malformed payload for mouse hover"),
1626 },
1627 None => Err("Malformed payload for MouseEventName"),
1628 }
1629 }
1630}
1631
1632impl TryFrom<Mouse> for MouseEventPayload {
1633 type Error = &'static str;
1634 fn try_from(mouse: Mouse) -> Result<Self, &'static str> {
1635 match mouse {
1636 Mouse::ScrollUp(number_of_lines) => Ok(MouseEventPayload {
1637 mouse_event_name: MouseEventName::MouseScrollUp as i32,
1638 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
1639 number_of_lines as u32,
1640 )),
1641 }),
1642 Mouse::ScrollDown(number_of_lines) => Ok(MouseEventPayload {
1643 mouse_event_name: MouseEventName::MouseScrollDown as i32,
1644 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
1645 number_of_lines as u32,
1646 )),
1647 }),
1648 Mouse::LeftClick(line, column) => Ok(MouseEventPayload {
1649 mouse_event_name: MouseEventName::MouseLeftClick as i32,
1650 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1651 ProtobufPosition {
1652 line: line as i64,
1653 column: column as i64,
1654 },
1655 )),
1656 }),
1657 Mouse::RightClick(line, column) => Ok(MouseEventPayload {
1658 mouse_event_name: MouseEventName::MouseRightClick as i32,
1659 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1660 ProtobufPosition {
1661 line: line as i64,
1662 column: column as i64,
1663 },
1664 )),
1665 }),
1666 Mouse::Hold(line, column) => Ok(MouseEventPayload {
1667 mouse_event_name: MouseEventName::MouseHold as i32,
1668 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1669 ProtobufPosition {
1670 line: line as i64,
1671 column: column as i64,
1672 },
1673 )),
1674 }),
1675 Mouse::Release(line, column) => Ok(MouseEventPayload {
1676 mouse_event_name: MouseEventName::MouseRelease as i32,
1677 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1678 ProtobufPosition {
1679 line: line as i64,
1680 column: column as i64,
1681 },
1682 )),
1683 }),
1684 Mouse::Hover(line, column) => Ok(MouseEventPayload {
1685 mouse_event_name: MouseEventName::MouseHover as i32,
1686 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1687 ProtobufPosition {
1688 line: line as i64,
1689 column: column as i64,
1690 },
1691 )),
1692 }),
1693 }
1694 }
1695}
1696
1697impl TryFrom<ProtobufPaneInfo> for PaneInfo {
1698 type Error = &'static str;
1699 fn try_from(protobuf_pane_info: ProtobufPaneInfo) -> Result<Self, &'static str> {
1700 Ok(PaneInfo {
1701 id: protobuf_pane_info.id,
1702 is_plugin: protobuf_pane_info.is_plugin,
1703 is_focused: protobuf_pane_info.is_focused,
1704 is_fullscreen: protobuf_pane_info.is_fullscreen,
1705 is_floating: protobuf_pane_info.is_floating,
1706 is_suppressed: protobuf_pane_info.is_suppressed,
1707 title: protobuf_pane_info.title,
1708 exited: protobuf_pane_info.exited,
1709 exit_status: protobuf_pane_info.exit_status,
1710 is_held: protobuf_pane_info.is_held,
1711 pane_x: protobuf_pane_info.pane_x as usize,
1712 pane_content_x: protobuf_pane_info.pane_content_x as usize,
1713 pane_y: protobuf_pane_info.pane_y as usize,
1714 pane_content_y: protobuf_pane_info.pane_content_y as usize,
1715 pane_rows: protobuf_pane_info.pane_rows as usize,
1716 pane_content_rows: protobuf_pane_info.pane_content_rows as usize,
1717 pane_columns: protobuf_pane_info.pane_columns as usize,
1718 pane_content_columns: protobuf_pane_info.pane_content_columns as usize,
1719 cursor_coordinates_in_pane: protobuf_pane_info
1720 .cursor_coordinates_in_pane
1721 .map(|position| (position.column as usize, position.line as usize)),
1722 terminal_command: protobuf_pane_info.terminal_command,
1723 plugin_url: protobuf_pane_info.plugin_url,
1724 is_selectable: protobuf_pane_info.is_selectable,
1725 index_in_pane_group: protobuf_pane_info
1726 .index_in_pane_group
1727 .iter()
1728 .map(|index_in_pane_group| {
1729 (
1730 index_in_pane_group.client_id as u16,
1731 index_in_pane_group.index as usize,
1732 )
1733 })
1734 .collect(),
1735 default_fg: protobuf_pane_info.default_fg,
1736 default_bg: protobuf_pane_info.default_bg,
1737 })
1738 }
1739}
1740
1741impl TryFrom<PaneInfo> for ProtobufPaneInfo {
1742 type Error = &'static str;
1743 fn try_from(pane_info: PaneInfo) -> Result<Self, &'static str> {
1744 Ok(ProtobufPaneInfo {
1745 id: pane_info.id,
1746 is_plugin: pane_info.is_plugin,
1747 is_focused: pane_info.is_focused,
1748 is_fullscreen: pane_info.is_fullscreen,
1749 is_floating: pane_info.is_floating,
1750 is_suppressed: pane_info.is_suppressed,
1751 title: pane_info.title,
1752 exited: pane_info.exited,
1753 exit_status: pane_info.exit_status,
1754 is_held: pane_info.is_held,
1755 pane_x: pane_info.pane_x as u32,
1756 pane_content_x: pane_info.pane_content_x as u32,
1757 pane_y: pane_info.pane_y as u32,
1758 pane_content_y: pane_info.pane_content_y as u32,
1759 pane_rows: pane_info.pane_rows as u32,
1760 pane_content_rows: pane_info.pane_content_rows as u32,
1761 pane_columns: pane_info.pane_columns as u32,
1762 pane_content_columns: pane_info.pane_content_columns as u32,
1763 cursor_coordinates_in_pane: pane_info.cursor_coordinates_in_pane.map(|(x, y)| {
1764 ProtobufPosition {
1765 column: x as i64,
1766 line: y as i64,
1767 }
1768 }),
1769 terminal_command: pane_info.terminal_command,
1770 plugin_url: pane_info.plugin_url,
1771 is_selectable: pane_info.is_selectable,
1772 index_in_pane_group: pane_info
1773 .index_in_pane_group
1774 .iter()
1775 .map(|(&client_id, &index)| IndexInPaneGroup {
1776 client_id: client_id as u32,
1777 index: index as u32,
1778 })
1779 .collect(),
1780 default_fg: pane_info.default_fg,
1781 default_bg: pane_info.default_bg,
1782 })
1783 }
1784}
1785
1786impl TryFrom<ProtobufTabInfo> for TabInfo {
1787 type Error = &'static str;
1788 fn try_from(protobuf_tab_info: ProtobufTabInfo) -> Result<Self, &'static str> {
1789 Ok(TabInfo {
1790 position: protobuf_tab_info.position as usize,
1791 name: protobuf_tab_info.name,
1792 active: protobuf_tab_info.active,
1793 panes_to_hide: protobuf_tab_info.panes_to_hide as usize,
1794 is_fullscreen_active: protobuf_tab_info.is_fullscreen_active,
1795 is_sync_panes_active: protobuf_tab_info.is_sync_panes_active,
1796 are_floating_panes_visible: protobuf_tab_info.are_floating_panes_visible,
1797 other_focused_clients: protobuf_tab_info
1798 .other_focused_clients
1799 .iter()
1800 .map(|c| *c as u16)
1801 .collect(),
1802 active_swap_layout_name: protobuf_tab_info.active_swap_layout_name,
1803 is_swap_layout_dirty: protobuf_tab_info.is_swap_layout_dirty,
1804 viewport_rows: protobuf_tab_info.viewport_rows as usize,
1805 viewport_columns: protobuf_tab_info.viewport_columns as usize,
1806 display_area_rows: protobuf_tab_info.display_area_rows as usize,
1807 display_area_columns: protobuf_tab_info.display_area_columns as usize,
1808 selectable_tiled_panes_count: protobuf_tab_info.selectable_tiled_panes_count as usize,
1809 selectable_floating_panes_count: protobuf_tab_info.selectable_floating_panes_count
1810 as usize,
1811 tab_id: protobuf_tab_info.tab_id as usize,
1812 has_bell_notification: protobuf_tab_info.has_bell_notification,
1813 is_flashing_bell: protobuf_tab_info.is_flashing_bell,
1814 })
1815 }
1816}
1817
1818impl TryFrom<TabInfo> for ProtobufTabInfo {
1819 type Error = &'static str;
1820 fn try_from(tab_info: TabInfo) -> Result<Self, &'static str> {
1821 Ok(ProtobufTabInfo {
1822 position: tab_info.position as u32,
1823 name: tab_info.name,
1824 active: tab_info.active,
1825 panes_to_hide: tab_info.panes_to_hide as u32,
1826 is_fullscreen_active: tab_info.is_fullscreen_active,
1827 is_sync_panes_active: tab_info.is_sync_panes_active,
1828 are_floating_panes_visible: tab_info.are_floating_panes_visible,
1829 other_focused_clients: tab_info
1830 .other_focused_clients
1831 .iter()
1832 .map(|c| *c as u32)
1833 .collect(),
1834 active_swap_layout_name: tab_info.active_swap_layout_name,
1835 is_swap_layout_dirty: tab_info.is_swap_layout_dirty,
1836 viewport_rows: tab_info.viewport_rows as u32,
1837 viewport_columns: tab_info.viewport_columns as u32,
1838 display_area_rows: tab_info.display_area_rows as u32,
1839 display_area_columns: tab_info.display_area_columns as u32,
1840 selectable_tiled_panes_count: tab_info.selectable_tiled_panes_count as u32,
1841 selectable_floating_panes_count: tab_info.selectable_floating_panes_count as u32,
1842 tab_id: tab_info.tab_id as u32,
1843 has_bell_notification: tab_info.has_bell_notification,
1844 is_flashing_bell: tab_info.is_flashing_bell,
1845 })
1846 }
1847}
1848
1849impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
1850 type Error = &'static str;
1851 fn try_from(
1852 mut protobuf_mode_update_payload: ProtobufModeUpdatePayload,
1853 ) -> Result<Self, &'static str> {
1854 let current_mode: InputMode =
1855 ProtobufInputMode::from_i32(protobuf_mode_update_payload.current_mode)
1856 .ok_or("Malformed InputMode in the ModeUpdate Event")?
1857 .try_into()?;
1858 let base_mode: Option<InputMode> = protobuf_mode_update_payload
1859 .base_mode
1860 .and_then(|b_m| ProtobufInputMode::from_i32(b_m)?.try_into().ok());
1861 let keybinds: Vec<(InputMode, Vec<(KeyWithModifier, Vec<Action>)>)> =
1862 protobuf_mode_update_payload
1863 .keybinds
1864 .iter_mut()
1865 .filter_map(|k| {
1866 let input_mode: InputMode = ProtobufInputMode::from_i32(k.mode)
1867 .ok_or("Malformed InputMode in the ModeUpdate Event")
1868 .ok()?
1869 .try_into()
1870 .ok()?;
1871 let mut keybinds: Vec<(KeyWithModifier, Vec<Action>)> = vec![];
1872 for mut protobuf_keybind in k.key_bind.drain(..) {
1873 let key: KeyWithModifier = protobuf_keybind.key.unwrap().try_into().ok()?;
1874 let mut actions: Vec<Action> = vec![];
1875 for action in protobuf_keybind.action.drain(..) {
1876 if let Ok(action) = action.try_into() {
1877 actions.push(action);
1878 }
1879 }
1880 keybinds.push((key, actions));
1881 }
1882 Some((input_mode, keybinds))
1883 })
1884 .collect();
1885 let style: Style = protobuf_mode_update_payload
1886 .style
1887 .and_then(|m| m.try_into().ok())
1888 .ok_or("malformed payload for mode_info")?;
1889 let session_name = protobuf_mode_update_payload.session_name;
1890 let editor = protobuf_mode_update_payload
1891 .editor
1892 .map(|e| PathBuf::from(e));
1893 let shell = protobuf_mode_update_payload.shell.map(|s| PathBuf::from(s));
1894 let web_clients_allowed = protobuf_mode_update_payload.web_clients_allowed;
1895 let web_sharing = protobuf_mode_update_payload
1896 .web_sharing
1897 .and_then(|w| ProtobufWebSharing::from_i32(w))
1898 .map(|w| w.into());
1899 let capabilities = PluginCapabilities {
1900 arrow_fonts: protobuf_mode_update_payload.arrow_fonts_support,
1901 };
1902 let currently_marking_pane_group =
1903 protobuf_mode_update_payload.currently_marking_pane_group;
1904 let is_web_client = protobuf_mode_update_payload.is_web_client;
1905
1906 let web_server_ip = protobuf_mode_update_payload
1907 .web_server_ip
1908 .as_ref()
1909 .and_then(|web_server_ip| IpAddr::from_str(web_server_ip).ok());
1910
1911 let web_server_port = protobuf_mode_update_payload
1912 .web_server_port
1913 .map(|w| w as u16);
1914
1915 let web_server_capability = protobuf_mode_update_payload.web_server_capability;
1916
1917 let mode_info = ModeInfo {
1918 mode: current_mode,
1919 keybinds,
1920 style,
1921 capabilities,
1922 session_name,
1923 base_mode,
1924 editor,
1925 shell,
1926 web_clients_allowed,
1927 web_sharing,
1928 currently_marking_pane_group,
1929 is_web_client,
1930 web_server_ip,
1931 web_server_port,
1932 web_server_capability,
1933 };
1934 Ok(mode_info)
1935 }
1936}
1937
1938impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
1939 type Error = &'static str;
1940 fn try_from(mode_info: ModeInfo) -> Result<Self, &'static str> {
1941 let current_mode: ProtobufInputMode = mode_info.mode.try_into()?;
1942 let base_mode: Option<ProtobufInputMode> = mode_info
1943 .base_mode
1944 .and_then(|mode| ProtobufInputMode::try_from(mode).ok());
1945 let style: ProtobufStyle = mode_info.style.try_into()?;
1946 let arrow_fonts_support: bool = mode_info.capabilities.arrow_fonts;
1947 let session_name = mode_info.session_name;
1948 let editor = mode_info.editor.map(|e| e.display().to_string());
1949 let shell = mode_info.shell.map(|s| s.display().to_string());
1950 let web_clients_allowed = mode_info.web_clients_allowed;
1951 let web_sharing = mode_info.web_sharing.map(|w| w as i32);
1952 let currently_marking_pane_group = mode_info.currently_marking_pane_group;
1953 let is_web_client = mode_info.is_web_client;
1954 let web_server_ip = mode_info.web_server_ip.map(|i| format!("{}", i));
1955 let web_server_port = mode_info.web_server_port.map(|p| p as u32);
1956 let web_server_capability = mode_info.web_server_capability;
1957 let mut protobuf_input_mode_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
1958 for (input_mode, input_mode_keybinds) in mode_info.keybinds {
1959 let mode: ProtobufInputMode = input_mode.try_into()?;
1960 let mut keybinds: Vec<ProtobufKeyBind> = vec![];
1961 for (key, actions) in input_mode_keybinds {
1962 let protobuf_key: ProtobufKey = key.try_into()?;
1963 let mut protobuf_actions: Vec<ProtobufAction> = vec![];
1964 for action in actions {
1965 if let Ok(protobuf_action) = action.try_into() {
1966 protobuf_actions.push(protobuf_action);
1967 }
1968 }
1969 let key_bind = ProtobufKeyBind {
1970 key: Some(protobuf_key),
1971 action: protobuf_actions,
1972 };
1973 keybinds.push(key_bind);
1974 }
1975 let input_mode_keybind = ProtobufInputModeKeybinds {
1976 mode: mode as i32,
1977 key_bind: keybinds,
1978 };
1979 protobuf_input_mode_keybinds.push(input_mode_keybind);
1980 }
1981 Ok(ProtobufModeUpdatePayload {
1982 current_mode: current_mode as i32,
1983 style: Some(style),
1984 keybinds: protobuf_input_mode_keybinds,
1985 arrow_fonts_support,
1986 session_name,
1987 base_mode: base_mode.map(|b_m| b_m as i32),
1988 editor,
1989 shell,
1990 web_clients_allowed,
1991 web_sharing,
1992 currently_marking_pane_group,
1993 is_web_client,
1994 web_server_ip,
1995 web_server_port,
1996 web_server_capability,
1997 })
1998 }
1999}
2000
2001impl TryFrom<ProtobufEventNameList> for HashSet<EventType> {
2002 type Error = &'static str;
2003 fn try_from(protobuf_event_name_list: ProtobufEventNameList) -> Result<Self, &'static str> {
2004 let event_types: Vec<ProtobufEventType> = protobuf_event_name_list
2005 .event_types
2006 .iter()
2007 .filter_map(|i| ProtobufEventType::from_i32(*i))
2008 .collect();
2009 let event_types: Vec<EventType> = event_types
2010 .iter()
2011 .filter_map(|e| EventType::try_from(*e).ok())
2012 .collect();
2013 Ok(event_types.into_iter().collect())
2014 }
2015}
2016
2017impl TryFrom<HashSet<EventType>> for ProtobufEventNameList {
2018 type Error = &'static str;
2019 fn try_from(event_types: HashSet<EventType>) -> Result<Self, &'static str> {
2020 let protobuf_event_name_list = ProtobufEventNameList {
2021 event_types: event_types
2022 .iter()
2023 .filter_map(|e| ProtobufEventType::try_from(*e).ok())
2024 .map(|e| e as i32)
2025 .collect(),
2026 };
2027 Ok(protobuf_event_name_list)
2028 }
2029}
2030
2031impl TryFrom<ProtobufEventType> for EventType {
2032 type Error = &'static str;
2033 fn try_from(protobuf_event_type: ProtobufEventType) -> Result<Self, &'static str> {
2034 Ok(match protobuf_event_type {
2035 ProtobufEventType::ModeUpdate => EventType::ModeUpdate,
2036 ProtobufEventType::TabUpdate => EventType::TabUpdate,
2037 ProtobufEventType::PaneUpdate => EventType::PaneUpdate,
2038 ProtobufEventType::Key => EventType::Key,
2039 ProtobufEventType::Mouse => EventType::Mouse,
2040 ProtobufEventType::Timer => EventType::Timer,
2041 ProtobufEventType::CopyToClipboard => EventType::CopyToClipboard,
2042 ProtobufEventType::SystemClipboardFailure => EventType::SystemClipboardFailure,
2043 ProtobufEventType::InputReceived => EventType::InputReceived,
2044 ProtobufEventType::Visible => EventType::Visible,
2045 ProtobufEventType::CustomMessage => EventType::CustomMessage,
2046 ProtobufEventType::FileSystemCreate => EventType::FileSystemCreate,
2047 ProtobufEventType::FileSystemRead => EventType::FileSystemRead,
2048 ProtobufEventType::FileSystemUpdate => EventType::FileSystemUpdate,
2049 ProtobufEventType::FileSystemDelete => EventType::FileSystemDelete,
2050 ProtobufEventType::PermissionRequestResult => EventType::PermissionRequestResult,
2051 ProtobufEventType::SessionUpdate => EventType::SessionUpdate,
2052 ProtobufEventType::RunCommandResult => EventType::RunCommandResult,
2053 ProtobufEventType::WebRequestResult => EventType::WebRequestResult,
2054 ProtobufEventType::CommandPaneOpened => EventType::CommandPaneOpened,
2055 ProtobufEventType::CommandPaneExited => EventType::CommandPaneExited,
2056 ProtobufEventType::PaneClosed => EventType::PaneClosed,
2057 ProtobufEventType::EditPaneOpened => EventType::EditPaneOpened,
2058 ProtobufEventType::EditPaneExited => EventType::EditPaneExited,
2059 ProtobufEventType::CommandPaneReRun => EventType::CommandPaneReRun,
2060 ProtobufEventType::FailedToWriteConfigToDisk => EventType::FailedToWriteConfigToDisk,
2061 ProtobufEventType::ListClients => EventType::ListClients,
2062 ProtobufEventType::HostFolderChanged => EventType::HostFolderChanged,
2063 ProtobufEventType::FailedToChangeHostFolder => EventType::FailedToChangeHostFolder,
2064 ProtobufEventType::PastedText => EventType::PastedText,
2065 ProtobufEventType::ConfigWasWrittenToDisk => EventType::ConfigWasWrittenToDisk,
2066 ProtobufEventType::WebServerStatus => EventType::WebServerStatus,
2067 ProtobufEventType::BeforeClose => EventType::BeforeClose,
2068 ProtobufEventType::FailedToStartWebServer => EventType::FailedToStartWebServer,
2069 ProtobufEventType::InterceptedKeyPress => EventType::InterceptedKeyPress,
2070 ProtobufEventType::PaneRenderReport => EventType::PaneRenderReport,
2071 ProtobufEventType::PaneRenderReportWithAnsi => EventType::PaneRenderReportWithAnsi,
2072 ProtobufEventType::UserAction => EventType::UserAction,
2073 ProtobufEventType::ActionComplete => EventType::ActionComplete,
2074 ProtobufEventType::CwdChanged => EventType::CwdChanged,
2075 ProtobufEventType::CommandChanged => EventType::CommandChanged,
2076 ProtobufEventType::AvailableLayoutInfo => EventType::AvailableLayoutInfo,
2077 ProtobufEventType::PluginConfigurationChanged => EventType::PluginConfigurationChanged,
2078 ProtobufEventType::HighlightClicked => EventType::HighlightClicked,
2079 ProtobufEventType::InitialKeybinds => EventType::InitialKeybinds,
2080 ProtobufEventType::HostTerminalThemeChanged => EventType::HostTerminalThemeChanged,
2081 })
2082 }
2083}
2084
2085impl TryFrom<EventType> for ProtobufEventType {
2086 type Error = &'static str;
2087 fn try_from(event_type: EventType) -> Result<Self, &'static str> {
2088 Ok(match event_type {
2089 EventType::ModeUpdate => ProtobufEventType::ModeUpdate,
2090 EventType::TabUpdate => ProtobufEventType::TabUpdate,
2091 EventType::PaneUpdate => ProtobufEventType::PaneUpdate,
2092 EventType::Key => ProtobufEventType::Key,
2093 EventType::Mouse => ProtobufEventType::Mouse,
2094 EventType::Timer => ProtobufEventType::Timer,
2095 EventType::CopyToClipboard => ProtobufEventType::CopyToClipboard,
2096 EventType::SystemClipboardFailure => ProtobufEventType::SystemClipboardFailure,
2097 EventType::InputReceived => ProtobufEventType::InputReceived,
2098 EventType::Visible => ProtobufEventType::Visible,
2099 EventType::CustomMessage => ProtobufEventType::CustomMessage,
2100 EventType::FileSystemCreate => ProtobufEventType::FileSystemCreate,
2101 EventType::FileSystemRead => ProtobufEventType::FileSystemRead,
2102 EventType::FileSystemUpdate => ProtobufEventType::FileSystemUpdate,
2103 EventType::FileSystemDelete => ProtobufEventType::FileSystemDelete,
2104 EventType::PermissionRequestResult => ProtobufEventType::PermissionRequestResult,
2105 EventType::SessionUpdate => ProtobufEventType::SessionUpdate,
2106 EventType::RunCommandResult => ProtobufEventType::RunCommandResult,
2107 EventType::WebRequestResult => ProtobufEventType::WebRequestResult,
2108 EventType::CommandPaneOpened => ProtobufEventType::CommandPaneOpened,
2109 EventType::CommandPaneExited => ProtobufEventType::CommandPaneExited,
2110 EventType::PaneClosed => ProtobufEventType::PaneClosed,
2111 EventType::EditPaneOpened => ProtobufEventType::EditPaneOpened,
2112 EventType::EditPaneExited => ProtobufEventType::EditPaneExited,
2113 EventType::CommandPaneReRun => ProtobufEventType::CommandPaneReRun,
2114 EventType::FailedToWriteConfigToDisk => ProtobufEventType::FailedToWriteConfigToDisk,
2115 EventType::ListClients => ProtobufEventType::ListClients,
2116 EventType::HostFolderChanged => ProtobufEventType::HostFolderChanged,
2117 EventType::FailedToChangeHostFolder => ProtobufEventType::FailedToChangeHostFolder,
2118 EventType::PastedText => ProtobufEventType::PastedText,
2119 EventType::ConfigWasWrittenToDisk => ProtobufEventType::ConfigWasWrittenToDisk,
2120 EventType::WebServerStatus => ProtobufEventType::WebServerStatus,
2121 EventType::BeforeClose => ProtobufEventType::BeforeClose,
2122 EventType::FailedToStartWebServer => ProtobufEventType::FailedToStartWebServer,
2123 EventType::InterceptedKeyPress => ProtobufEventType::InterceptedKeyPress,
2124 EventType::PaneRenderReport => ProtobufEventType::PaneRenderReport,
2125 EventType::PaneRenderReportWithAnsi => ProtobufEventType::PaneRenderReportWithAnsi,
2126 EventType::UserAction => ProtobufEventType::UserAction,
2127 EventType::ActionComplete => ProtobufEventType::ActionComplete,
2128 EventType::CwdChanged => ProtobufEventType::CwdChanged,
2129 EventType::CommandChanged => ProtobufEventType::CommandChanged,
2130 EventType::AvailableLayoutInfo => ProtobufEventType::AvailableLayoutInfo,
2131 EventType::PluginConfigurationChanged => ProtobufEventType::PluginConfigurationChanged,
2132 EventType::HighlightClicked => ProtobufEventType::HighlightClicked,
2133 EventType::InitialKeybinds => ProtobufEventType::InitialKeybinds,
2134 EventType::HostTerminalThemeChanged => ProtobufEventType::HostTerminalThemeChanged,
2135 })
2136 }
2137}
2138
2139impl From<HostTerminalThemeMode> for ProtobufHostTerminalThemeIndication {
2140 fn from(mode: HostTerminalThemeMode) -> Self {
2141 match mode {
2142 HostTerminalThemeMode::Dark => ProtobufHostTerminalThemeIndication::Dark,
2143 HostTerminalThemeMode::Light => ProtobufHostTerminalThemeIndication::Light,
2144 }
2145 }
2146}
2147
2148impl From<ProtobufHostTerminalThemeIndication> for HostTerminalThemeMode {
2149 fn from(mode: ProtobufHostTerminalThemeIndication) -> Self {
2150 match mode {
2151 ProtobufHostTerminalThemeIndication::Dark => HostTerminalThemeMode::Dark,
2152 ProtobufHostTerminalThemeIndication::Light => HostTerminalThemeMode::Light,
2153 }
2154 }
2155}
2156
2157impl From<ProtobufResurrectableSession> for (String, Duration) {
2158 fn from(protobuf_resurrectable_session: ProtobufResurrectableSession) -> (String, Duration) {
2159 (
2160 protobuf_resurrectable_session.name,
2161 Duration::from_secs(protobuf_resurrectable_session.creation_time),
2162 )
2163 }
2164}
2165
2166impl From<(String, Duration)> for ProtobufResurrectableSession {
2167 fn from(session_name_and_creation_time: (String, Duration)) -> ProtobufResurrectableSession {
2168 ProtobufResurrectableSession {
2169 name: session_name_and_creation_time.0,
2170 creation_time: session_name_and_creation_time.1.as_secs(),
2171 }
2172 }
2173}
2174
2175impl From<&ProtobufFileMetadata> for Option<FileMetadata> {
2176 fn from(protobuf_file_metadata: &ProtobufFileMetadata) -> Option<FileMetadata> {
2177 if protobuf_file_metadata.metadata_is_set {
2178 Some(FileMetadata {
2179 is_file: protobuf_file_metadata.is_file,
2180 is_dir: protobuf_file_metadata.is_dir,
2181 is_symlink: protobuf_file_metadata.is_symlink,
2182 len: protobuf_file_metadata.len,
2183 })
2184 } else {
2185 None
2186 }
2187 }
2188}
2189
2190impl From<Option<FileMetadata>> for ProtobufFileMetadata {
2191 fn from(file_metadata: Option<FileMetadata>) -> ProtobufFileMetadata {
2192 match file_metadata {
2193 Some(file_metadata) => ProtobufFileMetadata {
2194 metadata_is_set: true,
2195 is_file: file_metadata.is_file,
2196 is_dir: file_metadata.is_dir,
2197 is_symlink: file_metadata.is_symlink,
2198 len: file_metadata.len,
2199 },
2200 None => ProtobufFileMetadata {
2201 metadata_is_set: false,
2202 ..Default::default()
2203 },
2204 }
2205 }
2206}
2207
2208#[test]
2209fn serialize_mode_update_event() {
2210 use prost::Message;
2211 let mode_update_event = Event::ModeUpdate(Default::default());
2212 let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
2213 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2214 let deserialized_protobuf_event: ProtobufEvent =
2215 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2216 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2217 assert_eq!(
2218 mode_update_event, deserialized_event,
2219 "Event properly serialized/deserialized without change"
2220 );
2221}
2222
2223#[test]
2224fn serialize_mode_update_event_with_non_default_values() {
2225 use crate::data::{BareKey, Palette, PaletteColor, ThemeHue};
2226 use prost::Message;
2227 let mode_update_event = Event::ModeUpdate(ModeInfo {
2228 mode: InputMode::Locked,
2229 keybinds: vec![
2230 (
2231 InputMode::Locked,
2232 vec![(
2233 KeyWithModifier::new(BareKey::Char('b')).with_alt_modifier(),
2234 vec![Action::SwitchToMode {
2235 input_mode: InputMode::Normal,
2236 }],
2237 )],
2238 ),
2239 (
2240 InputMode::Tab,
2241 vec![(
2242 KeyWithModifier::new(BareKey::Up).with_alt_modifier(),
2243 vec![Action::SwitchToMode {
2244 input_mode: InputMode::Pane,
2245 }],
2246 )],
2247 ),
2248 (
2249 InputMode::Pane,
2250 vec![
2251 (
2252 KeyWithModifier::new(BareKey::Char('b')).with_ctrl_modifier(),
2253 vec![
2254 Action::SwitchToMode {
2255 input_mode: InputMode::Tmux,
2256 },
2257 Action::Write {
2258 key_with_modifier: None,
2259 bytes: vec![10],
2260 is_kitty_keyboard_protocol: false,
2261 },
2262 ],
2263 ),
2264 (
2265 KeyWithModifier::new(BareKey::Char('a')),
2266 vec![Action::WriteChars {
2267 chars: "foo".to_owned(),
2268 }],
2269 ),
2270 ],
2271 ),
2272 ],
2273 style: Style {
2274 colors: Palette {
2275 source: crate::data::PaletteSource::Default,
2276 theme_hue: ThemeHue::Light,
2277 fg: PaletteColor::Rgb((1, 1, 1)),
2278 bg: PaletteColor::Rgb((200, 200, 200)),
2279 black: PaletteColor::EightBit(1),
2280 red: PaletteColor::EightBit(2),
2281 green: PaletteColor::EightBit(2),
2282 yellow: PaletteColor::EightBit(2),
2283 blue: PaletteColor::EightBit(2),
2284 magenta: PaletteColor::EightBit(2),
2285 cyan: PaletteColor::EightBit(2),
2286 white: PaletteColor::EightBit(2),
2287 orange: PaletteColor::EightBit(2),
2288 gray: PaletteColor::EightBit(2),
2289 purple: PaletteColor::EightBit(2),
2290 gold: PaletteColor::EightBit(2),
2291 silver: PaletteColor::EightBit(2),
2292 pink: PaletteColor::EightBit(2),
2293 brown: PaletteColor::Rgb((222, 221, 220)),
2294 }
2295 .into(),
2296 rounded_corners: true,
2298 hide_session_name: false,
2299 },
2300 capabilities: PluginCapabilities { arrow_fonts: false },
2301 session_name: Some("my awesome test session".to_owned()),
2302 base_mode: Some(InputMode::Locked),
2303 editor: Some(PathBuf::from("my_awesome_editor")),
2304 shell: Some(PathBuf::from("my_awesome_shell")),
2305 web_clients_allowed: Some(true),
2306 web_sharing: Some(WebSharing::default()),
2307 currently_marking_pane_group: Some(false),
2308 is_web_client: Some(false),
2309 web_server_ip: IpAddr::from_str("127.0.0.1").ok(),
2310 web_server_port: Some(8082),
2311 web_server_capability: Some(true),
2312 });
2313 let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
2314 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2315 let deserialized_protobuf_event: ProtobufEvent =
2316 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2317 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2318 assert_eq!(
2319 mode_update_event, deserialized_event,
2320 "Event properly serialized/deserialized without change"
2321 );
2322}
2323
2324#[test]
2325fn serialize_tab_update_event() {
2326 use prost::Message;
2327 let tab_update_event = Event::TabUpdate(Default::default());
2328 let protobuf_event: ProtobufEvent = tab_update_event.clone().try_into().unwrap();
2329 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2330 let deserialized_protobuf_event: ProtobufEvent =
2331 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2332 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2333 assert_eq!(
2334 tab_update_event, deserialized_event,
2335 "Event properly serialized/deserialized without change"
2336 );
2337}
2338
2339#[test]
2340fn serialize_tab_update_event_with_non_default_values() {
2341 use prost::Message;
2342 let tab_update_event = Event::TabUpdate(vec![
2343 TabInfo {
2344 position: 0,
2345 name: "First tab".to_owned(),
2346 active: true,
2347 panes_to_hide: 2,
2348 is_fullscreen_active: true,
2349 is_sync_panes_active: false,
2350 are_floating_panes_visible: true,
2351 other_focused_clients: vec![2, 3, 4],
2352 active_swap_layout_name: Some("my cool swap layout".to_owned()),
2353 is_swap_layout_dirty: false,
2354 viewport_rows: 10,
2355 viewport_columns: 10,
2356 display_area_rows: 10,
2357 display_area_columns: 10,
2358 selectable_tiled_panes_count: 10,
2359 selectable_floating_panes_count: 10,
2360 tab_id: 0,
2361 has_bell_notification: false,
2362 is_flashing_bell: false,
2363 },
2364 TabInfo {
2365 position: 1,
2366 name: "Secondtab".to_owned(),
2367 active: false,
2368 panes_to_hide: 5,
2369 is_fullscreen_active: false,
2370 is_sync_panes_active: true,
2371 are_floating_panes_visible: true,
2372 other_focused_clients: vec![1, 5, 111],
2373 active_swap_layout_name: None,
2374 is_swap_layout_dirty: true,
2375 viewport_rows: 10,
2376 viewport_columns: 10,
2377 display_area_rows: 10,
2378 display_area_columns: 10,
2379 selectable_tiled_panes_count: 10,
2380 selectable_floating_panes_count: 10,
2381 tab_id: 1,
2382 has_bell_notification: false,
2383 is_flashing_bell: false,
2384 },
2385 TabInfo::default(),
2386 ]);
2387 let protobuf_event: ProtobufEvent = tab_update_event.clone().try_into().unwrap();
2388 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2389 let deserialized_protobuf_event: ProtobufEvent =
2390 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2391 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2392 assert_eq!(
2393 tab_update_event, deserialized_event,
2394 "Event properly serialized/deserialized without change"
2395 );
2396}
2397
2398#[test]
2399fn serialize_pane_update_event() {
2400 use prost::Message;
2401 let pane_update_event = Event::PaneUpdate(Default::default());
2402 let protobuf_event: ProtobufEvent = pane_update_event.clone().try_into().unwrap();
2403 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2404 let deserialized_protobuf_event: ProtobufEvent =
2405 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2406 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2407 assert_eq!(
2408 pane_update_event, deserialized_event,
2409 "Event properly serialized/deserialized without change"
2410 );
2411}
2412
2413#[test]
2414fn serialize_key_event() {
2415 use crate::data::BareKey;
2416 use prost::Message;
2417 let key_event = Event::Key(KeyWithModifier::new(BareKey::Char('a')).with_ctrl_modifier());
2418 let protobuf_event: ProtobufEvent = key_event.clone().try_into().unwrap();
2419 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2420 let deserialized_protobuf_event: ProtobufEvent =
2421 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2422 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2423 assert_eq!(
2424 key_event, deserialized_event,
2425 "Event properly serialized/deserialized without change"
2426 );
2427}
2428
2429#[test]
2430fn serialize_mouse_event() {
2431 use prost::Message;
2432 let mouse_event = Event::Mouse(Mouse::LeftClick(1, 1));
2433 let protobuf_event: ProtobufEvent = mouse_event.clone().try_into().unwrap();
2434 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2435 let deserialized_protobuf_event: ProtobufEvent =
2436 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2437 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2438 assert_eq!(
2439 mouse_event, deserialized_event,
2440 "Event properly serialized/deserialized without change"
2441 );
2442}
2443
2444#[test]
2445fn serialize_mouse_event_without_position() {
2446 use prost::Message;
2447 let mouse_event = Event::Mouse(Mouse::ScrollUp(17));
2448 let protobuf_event: ProtobufEvent = mouse_event.clone().try_into().unwrap();
2449 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2450 let deserialized_protobuf_event: ProtobufEvent =
2451 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2452 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2453 assert_eq!(
2454 mouse_event, deserialized_event,
2455 "Event properly serialized/deserialized without change"
2456 );
2457}
2458
2459#[test]
2460fn serialize_timer_event() {
2461 use prost::Message;
2462 let timer_event = Event::Timer(1.5);
2463 let protobuf_event: ProtobufEvent = timer_event.clone().try_into().unwrap();
2464 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2465 let deserialized_protobuf_event: ProtobufEvent =
2466 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2467 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2468 assert_eq!(
2469 timer_event, deserialized_event,
2470 "Event properly serialized/deserialized without change"
2471 );
2472}
2473
2474#[test]
2475fn serialize_copy_to_clipboard_event() {
2476 use prost::Message;
2477 let copy_event = Event::CopyToClipboard(CopyDestination::Primary);
2478 let protobuf_event: ProtobufEvent = copy_event.clone().try_into().unwrap();
2479 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2480 let deserialized_protobuf_event: ProtobufEvent =
2481 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2482 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2483 assert_eq!(
2484 copy_event, deserialized_event,
2485 "Event properly serialized/deserialized without change"
2486 );
2487}
2488
2489#[test]
2490fn serialize_clipboard_failure_event() {
2491 use prost::Message;
2492 let copy_event = Event::SystemClipboardFailure;
2493 let protobuf_event: ProtobufEvent = copy_event.clone().try_into().unwrap();
2494 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2495 let deserialized_protobuf_event: ProtobufEvent =
2496 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2497 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2498 assert_eq!(
2499 copy_event, deserialized_event,
2500 "Event properly serialized/deserialized without change"
2501 );
2502}
2503
2504#[test]
2505fn serialize_input_received_event() {
2506 use prost::Message;
2507 let input_received_event = Event::InputReceived;
2508 let protobuf_event: ProtobufEvent = input_received_event.clone().try_into().unwrap();
2509 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2510 let deserialized_protobuf_event: ProtobufEvent =
2511 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2512 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2513 assert_eq!(
2514 input_received_event, deserialized_event,
2515 "Event properly serialized/deserialized without change"
2516 );
2517}
2518
2519#[test]
2520fn serialize_visible_event() {
2521 use prost::Message;
2522 let visible_event = Event::Visible(true);
2523 let protobuf_event: ProtobufEvent = visible_event.clone().try_into().unwrap();
2524 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2525 let deserialized_protobuf_event: ProtobufEvent =
2526 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2527 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2528 assert_eq!(
2529 visible_event, deserialized_event,
2530 "Event properly serialized/deserialized without change"
2531 );
2532}
2533
2534#[test]
2535fn serialize_custom_message_event() {
2536 use prost::Message;
2537 let custom_message_event = Event::CustomMessage("foo".to_owned(), "bar".to_owned());
2538 let protobuf_event: ProtobufEvent = custom_message_event.clone().try_into().unwrap();
2539 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2540 let deserialized_protobuf_event: ProtobufEvent =
2541 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2542 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2543 assert_eq!(
2544 custom_message_event, deserialized_event,
2545 "Event properly serialized/deserialized without change"
2546 );
2547}
2548
2549#[test]
2550fn serialize_file_system_create_event() {
2551 use prost::Message;
2552 let file_system_event = Event::FileSystemCreate(vec![
2553 ("/absolute/path".into(), None),
2554 ("./relative_path".into(), Default::default()),
2555 ]);
2556 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2557 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2558 let deserialized_protobuf_event: ProtobufEvent =
2559 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2560 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2561 assert_eq!(
2562 file_system_event, deserialized_event,
2563 "Event properly serialized/deserialized without change"
2564 );
2565}
2566
2567#[test]
2568fn serialize_file_system_read_event() {
2569 use prost::Message;
2570 let file_system_event = Event::FileSystemRead(vec![
2571 ("/absolute/path".into(), None),
2572 ("./relative_path".into(), Default::default()),
2573 ]);
2574 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2575 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2576 let deserialized_protobuf_event: ProtobufEvent =
2577 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2578 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2579 assert_eq!(
2580 file_system_event, deserialized_event,
2581 "Event properly serialized/deserialized without change"
2582 );
2583}
2584
2585#[test]
2586fn serialize_file_system_update_event() {
2587 use prost::Message;
2588 let file_system_event = Event::FileSystemUpdate(vec![
2589 ("/absolute/path".into(), None),
2590 ("./relative_path".into(), Some(Default::default())),
2591 ]);
2592 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2593 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2594 let deserialized_protobuf_event: ProtobufEvent =
2595 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2596 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2597 assert_eq!(
2598 file_system_event, deserialized_event,
2599 "Event properly serialized/deserialized without change"
2600 );
2601}
2602
2603#[test]
2604fn serialize_file_system_delete_event() {
2605 use prost::Message;
2606 let file_system_event = Event::FileSystemDelete(vec![
2607 ("/absolute/path".into(), None),
2608 ("./relative_path".into(), Default::default()),
2609 ]);
2610 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2611 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2612 let deserialized_protobuf_event: ProtobufEvent =
2613 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2614 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2615 assert_eq!(
2616 file_system_event, deserialized_event,
2617 "Event properly serialized/deserialized without change"
2618 );
2619}
2620
2621#[test]
2622fn serialize_session_update_event() {
2623 use prost::Message;
2624 let session_update_event = Event::SessionUpdate(Default::default(), Default::default());
2625 let protobuf_event: ProtobufEvent = session_update_event.clone().try_into().unwrap();
2626 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2627 let deserialized_protobuf_event: ProtobufEvent =
2628 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2629 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2630 assert_eq!(
2631 session_update_event, deserialized_event,
2632 "Event properly serialized/deserialized without change"
2633 );
2634}
2635
2636#[test]
2637fn serialize_session_update_event_with_non_default_values() {
2638 use prost::Message;
2639 let tab_infos = vec![
2640 TabInfo {
2641 position: 0,
2642 name: "First tab".to_owned(),
2643 active: true,
2644 panes_to_hide: 2,
2645 is_fullscreen_active: true,
2646 is_sync_panes_active: false,
2647 are_floating_panes_visible: true,
2648 other_focused_clients: vec![2, 3, 4],
2649 active_swap_layout_name: Some("my cool swap layout".to_owned()),
2650 is_swap_layout_dirty: false,
2651 viewport_rows: 10,
2652 viewport_columns: 10,
2653 display_area_rows: 10,
2654 display_area_columns: 10,
2655 selectable_tiled_panes_count: 10,
2656 selectable_floating_panes_count: 10,
2657 tab_id: 0,
2658 has_bell_notification: false,
2659 is_flashing_bell: false,
2660 },
2661 TabInfo {
2662 position: 1,
2663 name: "Secondtab".to_owned(),
2664 active: false,
2665 panes_to_hide: 5,
2666 is_fullscreen_active: false,
2667 is_sync_panes_active: true,
2668 are_floating_panes_visible: true,
2669 other_focused_clients: vec![1, 5, 111],
2670 active_swap_layout_name: None,
2671 is_swap_layout_dirty: true,
2672 viewport_rows: 10,
2673 viewport_columns: 10,
2674 display_area_rows: 10,
2675 display_area_columns: 10,
2676 selectable_tiled_panes_count: 10,
2677 selectable_floating_panes_count: 10,
2678 tab_id: 1,
2679 has_bell_notification: false,
2680 is_flashing_bell: false,
2681 },
2682 TabInfo::default(),
2683 ];
2684 let mut panes = HashMap::new();
2685 let mut index_in_pane_group_1 = BTreeMap::new();
2686 index_in_pane_group_1.insert(1, 0);
2687 index_in_pane_group_1.insert(2, 0);
2688 index_in_pane_group_1.insert(3, 0);
2689 let mut index_in_pane_group_2 = BTreeMap::new();
2690 index_in_pane_group_2.insert(1, 1);
2691 index_in_pane_group_2.insert(2, 1);
2692 index_in_pane_group_2.insert(3, 1);
2693 let panes_list = vec![
2694 PaneInfo {
2695 id: 1,
2696 is_plugin: false,
2697 is_focused: true,
2698 is_fullscreen: true,
2699 is_floating: false,
2700 is_suppressed: false,
2701 title: "pane 1".to_owned(),
2702 exited: false,
2703 exit_status: None,
2704 is_held: false,
2705 pane_x: 0,
2706 pane_content_x: 1,
2707 pane_y: 0,
2708 pane_content_y: 1,
2709 pane_rows: 5,
2710 pane_content_rows: 4,
2711 pane_columns: 22,
2712 pane_content_columns: 21,
2713 cursor_coordinates_in_pane: Some((0, 0)),
2714 terminal_command: Some("foo".to_owned()),
2715 plugin_url: None,
2716 is_selectable: true,
2717 index_in_pane_group: index_in_pane_group_1,
2718 default_fg: None,
2719 default_bg: None,
2720 },
2721 PaneInfo {
2722 id: 1,
2723 is_plugin: true,
2724 is_focused: true,
2725 is_fullscreen: true,
2726 is_floating: false,
2727 is_suppressed: false,
2728 title: "pane 1".to_owned(),
2729 exited: false,
2730 exit_status: None,
2731 is_held: false,
2732 pane_x: 0,
2733 pane_content_x: 1,
2734 pane_y: 0,
2735 pane_content_y: 1,
2736 pane_rows: 5,
2737 pane_content_rows: 4,
2738 pane_columns: 22,
2739 pane_content_columns: 21,
2740 cursor_coordinates_in_pane: Some((0, 0)),
2741 terminal_command: None,
2742 plugin_url: Some("i_am_a_fake_plugin".to_owned()),
2743 is_selectable: true,
2744 index_in_pane_group: index_in_pane_group_2,
2745 default_fg: None,
2746 default_bg: None,
2747 },
2748 ];
2749 panes.insert(0, panes_list);
2750 let mut plugins = BTreeMap::new();
2751 let mut plugin_configuration = BTreeMap::new();
2752 plugin_configuration.insert("config_key".to_owned(), "config_value".to_owned());
2753 plugins.insert(
2754 1,
2755 PluginInfo {
2756 location: "https://example.com/my-plugin.wasm".to_owned(),
2757 configuration: plugin_configuration,
2758 },
2759 );
2760 let mut tab_history = BTreeMap::new();
2761 tab_history.insert(1, vec![1, 2, 3]);
2762 tab_history.insert(2, vec![1, 2, 3]);
2763 let session_info_1 = SessionInfo {
2764 name: "session 1".to_owned(),
2765 tabs: tab_infos,
2766 panes: PaneManifest { panes },
2767 connected_clients: 2,
2768 is_current_session: true,
2769 available_layouts: vec![
2770 LayoutInfo::File(
2771 "layout 1".to_owned(),
2772 LayoutMetadata {
2773 tabs: vec![],
2774 creation_time: "0".to_owned(),
2775 update_time: "0".to_owned(),
2776 },
2777 ),
2778 LayoutInfo::BuiltIn("layout2".to_owned()),
2779 LayoutInfo::File(
2780 "layout3".to_owned(),
2781 LayoutMetadata {
2782 tabs: vec![],
2783 creation_time: "0".to_owned(),
2784 update_time: "0".to_owned(),
2785 },
2786 ),
2787 ],
2788 plugins,
2789 web_clients_allowed: false,
2790 web_client_count: 1,
2791 tab_history,
2792 pane_history: Default::default(),
2793 creation_time: Duration::from_secs(100),
2794 };
2795 let session_info_2 = SessionInfo {
2796 name: "session 2".to_owned(),
2797 tabs: vec![],
2798 panes: PaneManifest {
2799 panes: HashMap::new(),
2800 },
2801 connected_clients: 0,
2802 is_current_session: false,
2803 available_layouts: vec![
2804 LayoutInfo::File(
2805 "layout 1".to_owned(),
2806 LayoutMetadata {
2807 tabs: vec![],
2808 creation_time: "0".to_owned(),
2809 update_time: "0".to_owned(),
2810 },
2811 ),
2812 LayoutInfo::BuiltIn("layout2".to_owned()),
2813 LayoutInfo::File(
2814 "layout3".to_owned(),
2815 LayoutMetadata {
2816 tabs: vec![],
2817 creation_time: "0".to_owned(),
2818 update_time: "0".to_owned(),
2819 },
2820 ),
2821 ],
2822 plugins: Default::default(),
2823 web_clients_allowed: false,
2824 web_client_count: 0,
2825 tab_history: Default::default(),
2826 pane_history: Default::default(),
2827 creation_time: Duration::from_secs(200),
2828 };
2829 let session_infos = vec![session_info_1, session_info_2];
2830 let resurrectable_sessions = vec![];
2831
2832 let session_update_event = Event::SessionUpdate(session_infos, resurrectable_sessions);
2833 let protobuf_event: ProtobufEvent = session_update_event.clone().try_into().unwrap();
2834 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2835 let deserialized_protobuf_event: ProtobufEvent =
2836 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2837 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2838 assert_eq!(
2839 session_update_event, deserialized_event,
2840 "Event properly serialized/deserialized without change"
2841 );
2842}
2843
2844impl TryFrom<ProtobufPaneId> for PaneId {
2848 type Error = &'static str;
2849 fn try_from(protobuf_pane_id: ProtobufPaneId) -> Result<Self, &'static str> {
2850 match ProtobufPaneType::from_i32(protobuf_pane_id.pane_type) {
2851 Some(ProtobufPaneType::Terminal) => Ok(PaneId::Terminal(protobuf_pane_id.id)),
2852 Some(ProtobufPaneType::Plugin) => Ok(PaneId::Plugin(protobuf_pane_id.id)),
2853 None => Err("Failed to convert PaneId"),
2854 }
2855 }
2856}
2857
2858impl TryFrom<PaneId> for ProtobufPaneId {
2862 type Error = &'static str;
2863 fn try_from(pane_id: PaneId) -> Result<Self, &'static str> {
2864 match pane_id {
2865 PaneId::Terminal(id) => Ok(ProtobufPaneId {
2866 pane_type: ProtobufPaneType::Terminal as i32,
2867 id,
2868 }),
2869 PaneId::Plugin(id) => Ok(ProtobufPaneId {
2870 pane_type: ProtobufPaneType::Plugin as i32,
2871 id,
2872 }),
2873 }
2874 }
2875}
2876
2877impl Into<ProtobufWebSharing> for WebSharing {
2878 fn into(self) -> ProtobufWebSharing {
2879 match self {
2880 WebSharing::On => ProtobufWebSharing::On,
2881 WebSharing::Off => ProtobufWebSharing::Off,
2882 WebSharing::Disabled => ProtobufWebSharing::Disabled,
2883 }
2884 }
2885}
2886
2887impl Into<WebSharing> for ProtobufWebSharing {
2888 fn into(self) -> WebSharing {
2889 match self {
2890 ProtobufWebSharing::On => WebSharing::On,
2891 ProtobufWebSharing::Off => WebSharing::Off,
2892 ProtobufWebSharing::Disabled => WebSharing::Disabled,
2893 }
2894 }
2895}
2896
2897impl TryFrom<WebServerStatus> for ProtobufWebServerStatusPayload {
2898 type Error = &'static str;
2899 fn try_from(web_server_status: WebServerStatus) -> Result<Self, &'static str> {
2900 match web_server_status {
2901 WebServerStatus::Online(url) => Ok(ProtobufWebServerStatusPayload {
2902 web_server_status_indication: WebServerStatusIndication::Online as i32,
2903 payload: Some(url),
2904 }),
2905 WebServerStatus::DifferentVersion(version) => Ok(ProtobufWebServerStatusPayload {
2906 web_server_status_indication: WebServerStatusIndication::DifferentVersion as i32,
2907 payload: Some(format!("{}", version)),
2908 }),
2909 WebServerStatus::Offline => Ok(ProtobufWebServerStatusPayload {
2910 web_server_status_indication: WebServerStatusIndication::Offline as i32,
2911 payload: None,
2912 }),
2913 }
2914 }
2915}
2916
2917impl TryFrom<ProtobufWebServerStatusPayload> for WebServerStatus {
2918 type Error = &'static str;
2919 fn try_from(
2920 protobuf_web_server_status: ProtobufWebServerStatusPayload,
2921 ) -> Result<Self, &'static str> {
2922 match WebServerStatusIndication::from_i32(
2923 protobuf_web_server_status.web_server_status_indication,
2924 ) {
2925 Some(WebServerStatusIndication::Online) => {
2926 let payload = protobuf_web_server_status
2927 .payload
2928 .ok_or("payload_not_found")?;
2929 Ok(WebServerStatus::Online(payload))
2930 },
2931 Some(WebServerStatusIndication::DifferentVersion) => {
2932 let payload = protobuf_web_server_status
2933 .payload
2934 .ok_or("payload_not_found")?;
2935 Ok(WebServerStatus::DifferentVersion(payload))
2936 },
2937 Some(WebServerStatusIndication::Offline) => Ok(WebServerStatus::Offline),
2938 None => Err("Unknown status"),
2939 }
2940 }
2941}
2942
2943impl TryFrom<ProtobufPaneRenderReportPayload> for HashMap<PaneId, PaneContents> {
2944 type Error = &'static str;
2945 fn try_from(protobuf_payload: ProtobufPaneRenderReportPayload) -> Result<Self, &'static str> {
2946 let mut pane_contents_map = HashMap::new();
2947
2948 for entry in protobuf_payload.pane_contents {
2949 let pane_id = entry
2950 .pane_id
2951 .ok_or("Missing pane_id in PaneContentsEntry")?
2952 .try_into()?;
2953 let pane_contents = entry
2954 .pane_contents
2955 .ok_or("Missing pane_contents in PaneContentsEntry")?
2956 .try_into()?;
2957 pane_contents_map.insert(pane_id, pane_contents);
2958 }
2959
2960 Ok(pane_contents_map)
2961 }
2962}
2963
2964impl TryFrom<HashMap<PaneId, PaneContents>> for ProtobufPaneRenderReportPayload {
2965 type Error = &'static str;
2966 fn try_from(pane_contents_map: HashMap<PaneId, PaneContents>) -> Result<Self, &'static str> {
2967 let mut pane_contents_vec = vec![];
2968
2969 for (pane_id, pane_contents) in pane_contents_map {
2970 pane_contents_vec.push(ProtobufPaneContentsEntry {
2971 pane_id: Some(pane_id.try_into()?),
2972 pane_contents: Some(pane_contents.try_into()?),
2973 });
2974 }
2975
2976 Ok(ProtobufPaneRenderReportPayload {
2977 pane_contents: pane_contents_vec,
2978 })
2979 }
2980}
2981
2982impl TryFrom<ProtobufPaneContents> for PaneContents {
2983 type Error = &'static str;
2984 fn try_from(protobuf_contents: ProtobufPaneContents) -> Result<Self, &'static str> {
2985 let selected_text = protobuf_contents
2986 .selected_text
2987 .map(|st| st.try_into())
2988 .transpose()?;
2989
2990 Ok(PaneContents {
2991 viewport: protobuf_contents.viewport,
2992 selected_text,
2993 lines_above_viewport: protobuf_contents.lines_above_viewport,
2994 lines_below_viewport: protobuf_contents.lines_below_viewport,
2995 })
2996 }
2997}
2998
2999impl TryFrom<PaneContents> for ProtobufPaneContents {
3000 type Error = &'static str;
3001 fn try_from(pane_contents: PaneContents) -> Result<Self, &'static str> {
3002 let selected_text = pane_contents
3003 .selected_text
3004 .map(|st| st.try_into())
3005 .transpose()?;
3006
3007 Ok(ProtobufPaneContents {
3008 viewport: pane_contents.viewport,
3009 selected_text,
3010 lines_above_viewport: pane_contents.lines_above_viewport,
3011 lines_below_viewport: pane_contents.lines_below_viewport,
3012 })
3013 }
3014}
3015
3016impl TryFrom<ProtobufPaneScrollbackResponse> for PaneScrollbackResponse {
3017 type Error = &'static str;
3018 fn try_from(protobuf_response: ProtobufPaneScrollbackResponse) -> Result<Self, &'static str> {
3019 match protobuf_response.response {
3020 Some(pane_scrollback_response::Response::Ok(pane_contents)) => {
3021 Ok(PaneScrollbackResponse::Ok(pane_contents.try_into()?))
3022 },
3023 Some(pane_scrollback_response::Response::Err(error_msg)) => {
3024 Ok(PaneScrollbackResponse::Err(error_msg))
3025 },
3026 None => Err("PaneScrollbackResponse missing response field"),
3027 }
3028 }
3029}
3030
3031impl TryFrom<PaneScrollbackResponse> for ProtobufPaneScrollbackResponse {
3032 type Error = &'static str;
3033 fn try_from(response: PaneScrollbackResponse) -> Result<Self, &'static str> {
3034 let response_field = match response {
3035 PaneScrollbackResponse::Ok(pane_contents) => {
3036 pane_scrollback_response::Response::Ok(pane_contents.try_into()?)
3037 },
3038 PaneScrollbackResponse::Err(error_msg) => {
3039 pane_scrollback_response::Response::Err(error_msg)
3040 },
3041 };
3042 Ok(ProtobufPaneScrollbackResponse {
3043 response: Some(response_field),
3044 })
3045 }
3046}
3047
3048impl TryFrom<ProtobufSelectedText> for SelectedText {
3049 type Error = &'static str;
3050 fn try_from(protobuf_selected_text: ProtobufSelectedText) -> Result<Self, &'static str> {
3051 Ok(SelectedText {
3052 start: protobuf_selected_text
3053 .start
3054 .ok_or("Missing start in SelectedText")?
3055 .try_into()?,
3056 end: protobuf_selected_text
3057 .end
3058 .ok_or("Missing end in SelectedText")?
3059 .try_into()?,
3060 })
3061 }
3062}
3063
3064impl TryFrom<SelectedText> for ProtobufSelectedText {
3065 type Error = &'static str;
3066 fn try_from(selected_text: SelectedText) -> Result<Self, &'static str> {
3067 Ok(ProtobufSelectedText {
3068 start: Some(selected_text.start.try_into()?),
3069 end: Some(selected_text.end.try_into()?),
3070 })
3071 }
3072}
3073
3074#[test]
3075fn serialize_pane_render_report_with_ansi_event() {
3076 use prost::Message;
3077 let pane_render_report_with_ansi_event = Event::PaneRenderReportWithAnsi(Default::default());
3078 let protobuf_event: ProtobufEvent = pane_render_report_with_ansi_event
3079 .clone()
3080 .try_into()
3081 .unwrap();
3082 let serialized_protobuf_event = protobuf_event.encode_to_vec();
3083 let deserialized_protobuf_event: ProtobufEvent =
3084 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
3085 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
3086 assert_eq!(
3087 pane_render_report_with_ansi_event, deserialized_event,
3088 "Event properly serialized/deserialized without change"
3089 );
3090}
3091
3092#[test]
3093fn serialize_pane_render_report_with_ansi_event_with_data() {
3094 use prost::Message;
3095 use std::collections::HashMap;
3096 let mut pane_contents_map = HashMap::new();
3097 pane_contents_map.insert(
3098 PaneId::Terminal(1),
3099 PaneContents {
3100 viewport: vec![
3101 "\x1b[31mred text\x1b[0m".to_owned(),
3102 "\x1b[1mbold text\x1b[0m".to_owned(),
3103 ],
3104 selected_text: None,
3105 lines_above_viewport: vec![],
3106 lines_below_viewport: vec![],
3107 },
3108 );
3109 let event = Event::PaneRenderReportWithAnsi(pane_contents_map);
3110 let protobuf_event: ProtobufEvent = event.clone().try_into().unwrap();
3111 let serialized_protobuf_event = protobuf_event.encode_to_vec();
3112 let deserialized_protobuf_event: ProtobufEvent =
3113 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
3114 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
3115 assert_eq!(
3116 event, deserialized_event,
3117 "PaneRenderReportWithAnsi event with ANSI data properly serialized/deserialized"
3118 );
3119}