1pub use super::generated_api::api::{
2 action::{Action as ProtobufAction, Position as ProtobufPosition},
3 event::{
4 event::Payload as ProtobufEventPayload, ClientInfo as ProtobufClientInfo,
5 CopyDestination as ProtobufCopyDestination, Event as ProtobufEvent,
6 EventNameList as ProtobufEventNameList, EventType as ProtobufEventType,
7 FileMetadata as ProtobufFileMetadata, InputModeKeybinds as ProtobufInputModeKeybinds,
8 KeyBind as ProtobufKeyBind, LayoutInfo as ProtobufLayoutInfo,
9 ModeUpdatePayload as ProtobufModeUpdatePayload, PaneId as ProtobufPaneId,
10 PaneInfo as ProtobufPaneInfo, PaneManifest as ProtobufPaneManifest,
11 PaneType as ProtobufPaneType, PluginInfo as ProtobufPluginInfo,
12 ResurrectableSession as ProtobufResurrectableSession,
13 SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, *,
14 },
15 input_mode::InputMode as ProtobufInputMode,
16 key::Key as ProtobufKey,
17 style::Style as ProtobufStyle,
18};
19#[allow(hidden_glob_reexports)]
20use crate::data::{
21 ClientInfo, CopyDestination, Event, EventType, FileMetadata, InputMode, KeyWithModifier,
22 LayoutInfo, ModeInfo, Mouse, PaneId, PaneInfo, PaneManifest, PermissionStatus,
23 PluginCapabilities, PluginInfo, SessionInfo, Style, TabInfo,
24};
25
26use crate::errors::prelude::*;
27use crate::input::actions::Action;
28
29use std::collections::{BTreeMap, HashMap, HashSet};
30use std::convert::TryFrom;
31use std::path::PathBuf;
32use std::time::Duration;
33
34impl TryFrom<ProtobufEvent> for Event {
35 type Error = &'static str;
36 fn try_from(protobuf_event: ProtobufEvent) -> Result<Self, &'static str> {
37 match ProtobufEventType::from_i32(protobuf_event.name) {
38 Some(ProtobufEventType::ModeUpdate) => match protobuf_event.payload {
39 Some(ProtobufEventPayload::ModeUpdatePayload(protobuf_mode_update_payload)) => {
40 let mode_info: ModeInfo = protobuf_mode_update_payload.try_into()?;
41 Ok(Event::ModeUpdate(mode_info))
42 },
43 _ => Err("Malformed payload for the ModeUpdate Event"),
44 },
45 Some(ProtobufEventType::TabUpdate) => match protobuf_event.payload {
46 Some(ProtobufEventPayload::TabUpdatePayload(protobuf_tab_info_payload)) => {
47 let mut tab_infos: Vec<TabInfo> = vec![];
48 for protobuf_tab_info in protobuf_tab_info_payload.tab_info {
49 tab_infos.push(TabInfo::try_from(protobuf_tab_info)?);
50 }
51 Ok(Event::TabUpdate(tab_infos))
52 },
53 _ => Err("Malformed payload for the TabUpdate Event"),
54 },
55 Some(ProtobufEventType::PaneUpdate) => match protobuf_event.payload {
56 Some(ProtobufEventPayload::PaneUpdatePayload(protobuf_pane_update_payload)) => {
57 let mut pane_manifest: HashMap<usize, Vec<PaneInfo>> = HashMap::new();
58 for protobuf_pane_manifest in protobuf_pane_update_payload.pane_manifest {
59 let tab_index = protobuf_pane_manifest.tab_index as usize;
60 let mut panes = vec![];
61 for protobuf_pane_info in protobuf_pane_manifest.panes {
62 panes.push(protobuf_pane_info.try_into()?);
63 }
64 if pane_manifest.contains_key(&tab_index) {
65 return Err("Duplicate tab definition in pane manifest");
66 }
67 pane_manifest.insert(tab_index, panes);
68 }
69 Ok(Event::PaneUpdate(PaneManifest {
70 panes: pane_manifest,
71 }))
72 },
73 _ => Err("Malformed payload for the PaneUpdate Event"),
74 },
75 Some(ProtobufEventType::Key) => match protobuf_event.payload {
76 Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => {
77 Ok(Event::Key(protobuf_key.try_into()?))
78 },
79 _ => Err("Malformed payload for the Key Event"),
80 },
81 Some(ProtobufEventType::Mouse) => match protobuf_event.payload {
82 Some(ProtobufEventPayload::MouseEventPayload(protobuf_mouse)) => {
83 Ok(Event::Mouse(protobuf_mouse.try_into()?))
84 },
85 _ => Err("Malformed payload for the Mouse Event"),
86 },
87 Some(ProtobufEventType::Timer) => match protobuf_event.payload {
88 Some(ProtobufEventPayload::TimerPayload(seconds)) => {
89 Ok(Event::Timer(seconds as f64))
90 },
91 _ => Err("Malformed payload for the Timer Event"),
92 },
93 Some(ProtobufEventType::CopyToClipboard) => match protobuf_event.payload {
94 Some(ProtobufEventPayload::CopyToClipboardPayload(copy_to_clipboard)) => {
95 let protobuf_copy_to_clipboard =
96 ProtobufCopyDestination::from_i32(copy_to_clipboard)
97 .ok_or("Malformed copy to clipboard payload")?;
98 Ok(Event::CopyToClipboard(
99 protobuf_copy_to_clipboard.try_into()?,
100 ))
101 },
102 _ => Err("Malformed payload for the Copy To Clipboard Event"),
103 },
104 Some(ProtobufEventType::SystemClipboardFailure) => match protobuf_event.payload {
105 None => Ok(Event::SystemClipboardFailure),
106 _ => Err("Malformed payload for the system clipboard failure Event"),
107 },
108 Some(ProtobufEventType::InputReceived) => match protobuf_event.payload {
109 None => Ok(Event::InputReceived),
110 _ => Err("Malformed payload for the input received Event"),
111 },
112 Some(ProtobufEventType::Visible) => match protobuf_event.payload {
113 Some(ProtobufEventPayload::VisiblePayload(is_visible)) => {
114 Ok(Event::Visible(is_visible))
115 },
116 _ => Err("Malformed payload for the visible Event"),
117 },
118 Some(ProtobufEventType::CustomMessage) => match protobuf_event.payload {
119 Some(ProtobufEventPayload::CustomMessagePayload(custom_message_payload)) => {
120 Ok(Event::CustomMessage(
121 custom_message_payload.message_name,
122 custom_message_payload.payload,
123 ))
124 },
125 _ => Err("Malformed payload for the custom message Event"),
126 },
127 Some(ProtobufEventType::FileSystemCreate) => match protobuf_event.payload {
128 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
129 let file_paths = file_list_payload
130 .paths
131 .iter()
132 .zip(file_list_payload.paths_metadata.iter())
133 .map(|(p, m)| (PathBuf::from(p), m.into()))
134 .collect();
135 Ok(Event::FileSystemCreate(file_paths))
136 },
137 _ => Err("Malformed payload for the file system create Event"),
138 },
139 Some(ProtobufEventType::FileSystemRead) => match protobuf_event.payload {
140 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
141 let file_paths = file_list_payload
142 .paths
143 .iter()
144 .zip(file_list_payload.paths_metadata.iter())
145 .map(|(p, m)| (PathBuf::from(p), m.into()))
146 .collect();
147 Ok(Event::FileSystemRead(file_paths))
148 },
149 _ => Err("Malformed payload for the file system read Event"),
150 },
151 Some(ProtobufEventType::FileSystemUpdate) => match protobuf_event.payload {
152 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
153 let file_paths = file_list_payload
154 .paths
155 .iter()
156 .zip(file_list_payload.paths_metadata.iter())
157 .map(|(p, m)| (PathBuf::from(p), m.into()))
158 .collect();
159 Ok(Event::FileSystemUpdate(file_paths))
160 },
161 _ => Err("Malformed payload for the file system update Event"),
162 },
163 Some(ProtobufEventType::FileSystemDelete) => match protobuf_event.payload {
164 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
165 let file_paths = file_list_payload
166 .paths
167 .iter()
168 .zip(file_list_payload.paths_metadata.iter())
169 .map(|(p, m)| (PathBuf::from(p), m.into()))
170 .collect();
171 Ok(Event::FileSystemDelete(file_paths))
172 },
173 _ => Err("Malformed payload for the file system delete Event"),
174 },
175 Some(ProtobufEventType::PermissionRequestResult) => match protobuf_event.payload {
176 Some(ProtobufEventPayload::PermissionRequestResultPayload(payload)) => {
177 if payload.granted {
178 Ok(Event::PermissionRequestResult(PermissionStatus::Granted))
179 } else {
180 Ok(Event::PermissionRequestResult(PermissionStatus::Denied))
181 }
182 },
183 _ => Err("Malformed payload for the file system delete Event"),
184 },
185 Some(ProtobufEventType::SessionUpdate) => match protobuf_event.payload {
186 Some(ProtobufEventPayload::SessionUpdatePayload(
187 protobuf_session_update_payload,
188 )) => {
189 let mut session_infos: Vec<SessionInfo> = vec![];
190 let mut resurrectable_sessions: Vec<(String, Duration)> = vec![];
191 for protobuf_session_info in protobuf_session_update_payload.session_manifests {
192 session_infos.push(SessionInfo::try_from(protobuf_session_info)?);
193 }
194 for protobuf_resurrectable_session in
195 protobuf_session_update_payload.resurrectable_sessions
196 {
197 resurrectable_sessions.push(protobuf_resurrectable_session.into());
198 }
199 Ok(Event::SessionUpdate(
200 session_infos,
201 resurrectable_sessions.into(),
202 ))
203 },
204 _ => Err("Malformed payload for the SessionUpdate Event"),
205 },
206 Some(ProtobufEventType::RunCommandResult) => match protobuf_event.payload {
207 Some(ProtobufEventPayload::RunCommandResultPayload(run_command_result_payload)) => {
208 Ok(Event::RunCommandResult(
209 run_command_result_payload.exit_code,
210 run_command_result_payload.stdout,
211 run_command_result_payload.stderr,
212 run_command_result_payload
213 .context
214 .into_iter()
215 .map(|c_i| (c_i.name, c_i.value))
216 .collect(),
217 ))
218 },
219 _ => Err("Malformed payload for the RunCommandResult Event"),
220 },
221 Some(ProtobufEventType::WebRequestResult) => match protobuf_event.payload {
222 Some(ProtobufEventPayload::WebRequestResultPayload(web_request_result_payload)) => {
223 Ok(Event::WebRequestResult(
224 web_request_result_payload.status as u16,
225 web_request_result_payload
226 .headers
227 .into_iter()
228 .map(|h| (h.name, h.value))
229 .collect(),
230 web_request_result_payload.body,
231 web_request_result_payload
232 .context
233 .into_iter()
234 .map(|c_i| (c_i.name, c_i.value))
235 .collect(),
236 ))
237 },
238 _ => Err("Malformed payload for the WebRequestResult Event"),
239 },
240 Some(ProtobufEventType::CommandPaneOpened) => match protobuf_event.payload {
241 Some(ProtobufEventPayload::CommandPaneOpenedPayload(
242 command_pane_opened_payload,
243 )) => Ok(Event::CommandPaneOpened(
244 command_pane_opened_payload.terminal_pane_id,
245 command_pane_opened_payload
246 .context
247 .into_iter()
248 .map(|c_i| (c_i.name, c_i.value))
249 .collect(),
250 )),
251 _ => Err("Malformed payload for the CommandPaneOpened Event"),
252 },
253 Some(ProtobufEventType::CommandPaneExited) => match protobuf_event.payload {
254 Some(ProtobufEventPayload::CommandPaneExitedPayload(
255 command_pane_exited_payload,
256 )) => Ok(Event::CommandPaneExited(
257 command_pane_exited_payload.terminal_pane_id,
258 command_pane_exited_payload.exit_code,
259 command_pane_exited_payload
260 .context
261 .into_iter()
262 .map(|c_i| (c_i.name, c_i.value))
263 .collect(),
264 )),
265 _ => Err("Malformed payload for the CommandPaneExited Event"),
266 },
267 Some(ProtobufEventType::PaneClosed) => match protobuf_event.payload {
268 Some(ProtobufEventPayload::PaneClosedPayload(pane_closed_payload)) => {
269 let pane_id = pane_closed_payload
270 .pane_id
271 .ok_or("Malformed payload for the PaneClosed Event")?;
272 Ok(Event::PaneClosed(PaneId::try_from(pane_id)?))
273 },
274 _ => Err("Malformed payload for the PaneClosed Event"),
275 },
276 Some(ProtobufEventType::EditPaneOpened) => match protobuf_event.payload {
277 Some(ProtobufEventPayload::EditPaneOpenedPayload(command_pane_opened_payload)) => {
278 Ok(Event::EditPaneOpened(
279 command_pane_opened_payload.terminal_pane_id,
280 command_pane_opened_payload
281 .context
282 .into_iter()
283 .map(|c_i| (c_i.name, c_i.value))
284 .collect(),
285 ))
286 },
287 _ => Err("Malformed payload for the EditPaneOpened Event"),
288 },
289 Some(ProtobufEventType::EditPaneExited) => match protobuf_event.payload {
290 Some(ProtobufEventPayload::EditPaneExitedPayload(command_pane_exited_payload)) => {
291 Ok(Event::EditPaneExited(
292 command_pane_exited_payload.terminal_pane_id,
293 command_pane_exited_payload.exit_code,
294 command_pane_exited_payload
295 .context
296 .into_iter()
297 .map(|c_i| (c_i.name, c_i.value))
298 .collect(),
299 ))
300 },
301 _ => Err("Malformed payload for the EditPaneExited Event"),
302 },
303 Some(ProtobufEventType::CommandPaneReRun) => match protobuf_event.payload {
304 Some(ProtobufEventPayload::CommandPaneRerunPayload(command_pane_rerun_payload)) => {
305 Ok(Event::CommandPaneReRun(
306 command_pane_rerun_payload.terminal_pane_id,
307 command_pane_rerun_payload
308 .context
309 .into_iter()
310 .map(|c_i| (c_i.name, c_i.value))
311 .collect(),
312 ))
313 },
314 _ => Err("Malformed payload for the CommandPaneReRun Event"),
315 },
316 Some(ProtobufEventType::FailedToWriteConfigToDisk) => match protobuf_event.payload {
317 Some(ProtobufEventPayload::FailedToWriteConfigToDiskPayload(
318 failed_to_write_configuration_payload,
319 )) => Ok(Event::FailedToWriteConfigToDisk(
320 failed_to_write_configuration_payload.file_path,
321 )),
322 _ => Err("Malformed payload for the FailedToWriteConfigToDisk Event"),
323 },
324 Some(ProtobufEventType::ListClients) => match protobuf_event.payload {
325 Some(ProtobufEventPayload::ListClientsPayload(mut list_clients_payload)) => {
326 Ok(Event::ListClients(
327 list_clients_payload
328 .client_info
329 .drain(..)
330 .filter_map(|c| c.try_into().ok())
331 .collect(),
332 ))
333 },
334 _ => Err("Malformed payload for the FailedToWriteConfigToDisk Event"),
335 },
336 None => Err("Unknown Protobuf Event"),
337 }
338 }
339}
340
341impl TryFrom<ProtobufClientInfo> for ClientInfo {
342 type Error = &'static str;
343 fn try_from(protobuf_client_info: ProtobufClientInfo) -> Result<Self, &'static str> {
344 Ok(ClientInfo::new(
345 protobuf_client_info.client_id as u16,
346 protobuf_client_info
347 .pane_id
348 .ok_or("No pane id found")?
349 .try_into()?,
350 protobuf_client_info.running_command,
351 protobuf_client_info.is_current_client,
352 ))
353 }
354}
355
356impl TryFrom<ClientInfo> for ProtobufClientInfo {
357 type Error = &'static str;
358 fn try_from(client_info: ClientInfo) -> Result<Self, &'static str> {
359 Ok(ProtobufClientInfo {
360 client_id: client_info.client_id as u32,
361 pane_id: Some(client_info.pane_id.try_into()?),
362 running_command: client_info.running_command,
363 is_current_client: client_info.is_current_client,
364 })
365 }
366}
367
368impl TryFrom<Event> for ProtobufEvent {
369 type Error = &'static str;
370 fn try_from(event: Event) -> Result<Self, &'static str> {
371 match event {
372 Event::ModeUpdate(mode_info) => {
373 let protobuf_mode_update_payload = mode_info.try_into()?;
374 Ok(ProtobufEvent {
375 name: ProtobufEventType::ModeUpdate as i32,
376 payload: Some(event::Payload::ModeUpdatePayload(
377 protobuf_mode_update_payload,
378 )),
379 })
380 },
381 Event::TabUpdate(tab_infos) => {
382 let mut protobuf_tab_infos = vec![];
383 for tab_info in tab_infos {
384 protobuf_tab_infos.push(tab_info.try_into()?);
385 }
386 let tab_update_payload = TabUpdatePayload {
387 tab_info: protobuf_tab_infos,
388 };
389 Ok(ProtobufEvent {
390 name: ProtobufEventType::TabUpdate as i32,
391 payload: Some(event::Payload::TabUpdatePayload(tab_update_payload)),
392 })
393 },
394 Event::PaneUpdate(pane_manifest) => {
395 let mut protobuf_pane_manifests = vec![];
396 for (tab_index, pane_infos) in pane_manifest.panes {
397 let mut protobuf_pane_infos = vec![];
398 for pane_info in pane_infos {
399 protobuf_pane_infos.push(pane_info.try_into()?);
400 }
401 protobuf_pane_manifests.push(ProtobufPaneManifest {
402 tab_index: tab_index as u32,
403 panes: protobuf_pane_infos,
404 });
405 }
406 Ok(ProtobufEvent {
407 name: ProtobufEventType::PaneUpdate as i32,
408 payload: Some(event::Payload::PaneUpdatePayload(PaneUpdatePayload {
409 pane_manifest: protobuf_pane_manifests,
410 })),
411 })
412 },
413 Event::Key(key) => Ok(ProtobufEvent {
414 name: ProtobufEventType::Key as i32,
415 payload: Some(event::Payload::KeyPayload(key.try_into()?)),
416 }),
417 Event::Mouse(mouse_event) => {
418 let protobuf_mouse_payload = mouse_event.try_into()?;
419 Ok(ProtobufEvent {
420 name: ProtobufEventType::Mouse as i32,
421 payload: Some(event::Payload::MouseEventPayload(protobuf_mouse_payload)),
422 })
423 },
424 Event::Timer(seconds) => Ok(ProtobufEvent {
425 name: ProtobufEventType::Timer as i32,
426 payload: Some(event::Payload::TimerPayload(seconds as f32)),
427 }),
428 Event::CopyToClipboard(clipboard_destination) => {
429 let protobuf_copy_destination: ProtobufCopyDestination =
430 clipboard_destination.try_into()?;
431 Ok(ProtobufEvent {
432 name: ProtobufEventType::CopyToClipboard as i32,
433 payload: Some(event::Payload::CopyToClipboardPayload(
434 protobuf_copy_destination as i32,
435 )),
436 })
437 },
438 Event::SystemClipboardFailure => Ok(ProtobufEvent {
439 name: ProtobufEventType::SystemClipboardFailure as i32,
440 payload: None,
441 }),
442 Event::InputReceived => Ok(ProtobufEvent {
443 name: ProtobufEventType::InputReceived as i32,
444 payload: None,
445 }),
446 Event::Visible(is_visible) => Ok(ProtobufEvent {
447 name: ProtobufEventType::Visible as i32,
448 payload: Some(event::Payload::VisiblePayload(is_visible)),
449 }),
450 Event::CustomMessage(message, payload) => Ok(ProtobufEvent {
451 name: ProtobufEventType::CustomMessage as i32,
452 payload: Some(event::Payload::CustomMessagePayload(CustomMessagePayload {
453 message_name: message,
454 payload,
455 })),
456 }),
457 Event::FileSystemCreate(event_paths) => {
458 let mut paths = vec![];
459 let mut paths_metadata = vec![];
460 for (path, path_metadata) in event_paths {
461 paths.push(path.display().to_string());
462 paths_metadata.push(path_metadata.into());
463 }
464 let file_list_payload = FileListPayload {
465 paths,
466 paths_metadata,
467 };
468 Ok(ProtobufEvent {
469 name: ProtobufEventType::FileSystemCreate as i32,
470 payload: Some(event::Payload::FileListPayload(file_list_payload)),
471 })
472 },
473 Event::FileSystemRead(event_paths) => {
474 let mut paths = vec![];
475 let mut paths_metadata = vec![];
476 for (path, path_metadata) in event_paths {
477 paths.push(path.display().to_string());
478 paths_metadata.push(path_metadata.into());
479 }
480 let file_list_payload = FileListPayload {
481 paths,
482 paths_metadata,
483 };
484 Ok(ProtobufEvent {
485 name: ProtobufEventType::FileSystemRead as i32,
486 payload: Some(event::Payload::FileListPayload(file_list_payload)),
487 })
488 },
489 Event::FileSystemUpdate(event_paths) => {
490 let mut paths = vec![];
491 let mut paths_metadata = vec![];
492 for (path, path_metadata) in event_paths {
493 paths.push(path.display().to_string());
494 paths_metadata.push(path_metadata.into());
495 }
496 let file_list_payload = FileListPayload {
497 paths,
498 paths_metadata,
499 };
500 Ok(ProtobufEvent {
501 name: ProtobufEventType::FileSystemUpdate as i32,
502 payload: Some(event::Payload::FileListPayload(file_list_payload)),
503 })
504 },
505 Event::FileSystemDelete(event_paths) => {
506 let mut paths = vec![];
507 let mut paths_metadata = vec![];
508 for (path, path_metadata) in event_paths {
509 paths.push(path.display().to_string());
510 paths_metadata.push(path_metadata.into());
511 }
512 let file_list_payload = FileListPayload {
513 paths,
514 paths_metadata,
515 };
516 Ok(ProtobufEvent {
517 name: ProtobufEventType::FileSystemDelete as i32,
518 payload: Some(event::Payload::FileListPayload(file_list_payload)),
519 })
520 },
521 Event::PermissionRequestResult(permission_status) => {
522 let granted = match permission_status {
523 PermissionStatus::Granted => true,
524 PermissionStatus::Denied => false,
525 };
526 Ok(ProtobufEvent {
527 name: ProtobufEventType::PermissionRequestResult as i32,
528 payload: Some(event::Payload::PermissionRequestResultPayload(
529 PermissionRequestResultPayload { granted },
530 )),
531 })
532 },
533 Event::SessionUpdate(session_infos, resurrectable_sessions) => {
534 let mut protobuf_session_manifests = vec![];
535 for session_info in session_infos {
536 protobuf_session_manifests.push(session_info.try_into()?);
537 }
538 let mut protobuf_resurrectable_sessions = vec![];
539 for resurrectable_session in resurrectable_sessions {
540 protobuf_resurrectable_sessions.push(resurrectable_session.into());
541 }
542 let session_update_payload = SessionUpdatePayload {
543 session_manifests: protobuf_session_manifests,
544 resurrectable_sessions: protobuf_resurrectable_sessions,
545 };
546 Ok(ProtobufEvent {
547 name: ProtobufEventType::SessionUpdate as i32,
548 payload: Some(event::Payload::SessionUpdatePayload(session_update_payload)),
549 })
550 },
551 Event::RunCommandResult(exit_code, stdout, stderr, context) => {
552 let run_command_result_payload = RunCommandResultPayload {
553 exit_code,
554 stdout,
555 stderr,
556 context: context
557 .into_iter()
558 .map(|(name, value)| ContextItem { name, value })
559 .collect(),
560 };
561 Ok(ProtobufEvent {
562 name: ProtobufEventType::RunCommandResult as i32,
563 payload: Some(event::Payload::RunCommandResultPayload(
564 run_command_result_payload,
565 )),
566 })
567 },
568 Event::WebRequestResult(status, headers, body, context) => {
569 let web_request_result_payload = WebRequestResultPayload {
570 status: status as i32,
571 headers: headers
572 .into_iter()
573 .map(|(name, value)| Header { name, value })
574 .collect(),
575 body,
576 context: context
577 .into_iter()
578 .map(|(name, value)| ContextItem { name, value })
579 .collect(),
580 };
581 Ok(ProtobufEvent {
582 name: ProtobufEventType::WebRequestResult as i32,
583 payload: Some(event::Payload::WebRequestResultPayload(
584 web_request_result_payload,
585 )),
586 })
587 },
588 Event::CommandPaneOpened(terminal_pane_id, context) => {
589 let command_pane_opened_payload = CommandPaneOpenedPayload {
590 terminal_pane_id,
591 context: context
592 .into_iter()
593 .map(|(name, value)| ContextItem { name, value })
594 .collect(),
595 };
596 Ok(ProtobufEvent {
597 name: ProtobufEventType::CommandPaneOpened as i32,
598 payload: Some(event::Payload::CommandPaneOpenedPayload(
599 command_pane_opened_payload,
600 )),
601 })
602 },
603 Event::CommandPaneExited(terminal_pane_id, exit_code, context) => {
604 let command_pane_exited_payload = CommandPaneExitedPayload {
605 terminal_pane_id,
606 exit_code,
607 context: context
608 .into_iter()
609 .map(|(name, value)| ContextItem { name, value })
610 .collect(),
611 };
612 Ok(ProtobufEvent {
613 name: ProtobufEventType::CommandPaneExited as i32,
614 payload: Some(event::Payload::CommandPaneExitedPayload(
615 command_pane_exited_payload,
616 )),
617 })
618 },
619 Event::PaneClosed(pane_id) => Ok(ProtobufEvent {
620 name: ProtobufEventType::PaneClosed as i32,
621 payload: Some(event::Payload::PaneClosedPayload(PaneClosedPayload {
622 pane_id: Some(pane_id.try_into()?),
623 })),
624 }),
625 Event::EditPaneOpened(terminal_pane_id, context) => {
626 let command_pane_opened_payload = EditPaneOpenedPayload {
627 terminal_pane_id,
628 context: context
629 .into_iter()
630 .map(|(name, value)| ContextItem { name, value })
631 .collect(),
632 };
633 Ok(ProtobufEvent {
634 name: ProtobufEventType::EditPaneOpened as i32,
635 payload: Some(event::Payload::EditPaneOpenedPayload(
636 command_pane_opened_payload,
637 )),
638 })
639 },
640 Event::EditPaneExited(terminal_pane_id, exit_code, context) => {
641 let command_pane_exited_payload = EditPaneExitedPayload {
642 terminal_pane_id,
643 exit_code,
644 context: context
645 .into_iter()
646 .map(|(name, value)| ContextItem { name, value })
647 .collect(),
648 };
649 Ok(ProtobufEvent {
650 name: ProtobufEventType::EditPaneExited as i32,
651 payload: Some(event::Payload::EditPaneExitedPayload(
652 command_pane_exited_payload,
653 )),
654 })
655 },
656 Event::CommandPaneReRun(terminal_pane_id, context) => {
657 let command_pane_rerun_payload = CommandPaneReRunPayload {
658 terminal_pane_id,
659 context: context
660 .into_iter()
661 .map(|(name, value)| ContextItem { name, value })
662 .collect(),
663 };
664 Ok(ProtobufEvent {
665 name: ProtobufEventType::CommandPaneReRun as i32,
666 payload: Some(event::Payload::CommandPaneRerunPayload(
667 command_pane_rerun_payload,
668 )),
669 })
670 },
671 Event::FailedToWriteConfigToDisk(file_path) => Ok(ProtobufEvent {
672 name: ProtobufEventType::FailedToWriteConfigToDisk as i32,
673 payload: Some(event::Payload::FailedToWriteConfigToDiskPayload(
674 FailedToWriteConfigToDiskPayload { file_path },
675 )),
676 }),
677 Event::ListClients(mut client_info_list) => Ok(ProtobufEvent {
678 name: ProtobufEventType::ListClients as i32,
679 payload: Some(event::Payload::ListClientsPayload(ListClientsPayload {
680 client_info: client_info_list
681 .drain(..)
682 .filter_map(|c| c.try_into().ok())
683 .collect(),
684 })),
685 }),
686 }
687 }
688}
689
690impl TryFrom<SessionInfo> for ProtobufSessionManifest {
691 type Error = &'static str;
692 fn try_from(session_info: SessionInfo) -> Result<Self, &'static str> {
693 let mut protobuf_pane_manifests = vec![];
694 for (tab_index, pane_infos) in session_info.panes.panes {
695 let mut protobuf_pane_infos = vec![];
696 for pane_info in pane_infos {
697 protobuf_pane_infos.push(pane_info.try_into()?);
698 }
699 protobuf_pane_manifests.push(ProtobufPaneManifest {
700 tab_index: tab_index as u32,
701 panes: protobuf_pane_infos,
702 });
703 }
704 Ok(ProtobufSessionManifest {
705 name: session_info.name,
706 panes: protobuf_pane_manifests,
707 tabs: session_info
708 .tabs
709 .iter()
710 .filter_map(|t| t.clone().try_into().ok())
711 .collect(),
712 connected_clients: session_info.connected_clients as u32,
713 is_current_session: session_info.is_current_session,
714 available_layouts: session_info
715 .available_layouts
716 .into_iter()
717 .filter_map(|l| ProtobufLayoutInfo::try_from(l).ok())
718 .collect(),
719 plugins: session_info
720 .plugins
721 .into_iter()
722 .map(|p| ProtobufPluginInfo::from(p))
723 .collect(),
724 })
725 }
726}
727
728impl From<(u32, PluginInfo)> for ProtobufPluginInfo {
729 fn from((plugin_id, plugin_info): (u32, PluginInfo)) -> ProtobufPluginInfo {
730 ProtobufPluginInfo {
731 plugin_id,
732 plugin_url: plugin_info.location,
733 plugin_config: plugin_info
734 .configuration
735 .into_iter()
736 .map(|(name, value)| ContextItem { name, value })
737 .collect(),
738 }
739 }
740}
741
742impl TryFrom<ProtobufSessionManifest> for SessionInfo {
743 type Error = &'static str;
744 fn try_from(protobuf_session_manifest: ProtobufSessionManifest) -> Result<Self, &'static str> {
745 let mut pane_manifest: HashMap<usize, Vec<PaneInfo>> = HashMap::new();
746 for protobuf_pane_manifest in protobuf_session_manifest.panes {
747 let tab_index = protobuf_pane_manifest.tab_index as usize;
748 let mut panes = vec![];
749 for protobuf_pane_info in protobuf_pane_manifest.panes {
750 panes.push(protobuf_pane_info.try_into()?);
751 }
752 if pane_manifest.contains_key(&tab_index) {
753 return Err("Duplicate tab definition in pane manifest");
754 }
755 pane_manifest.insert(tab_index, panes);
756 }
757 let panes = PaneManifest {
758 panes: pane_manifest,
759 };
760 let mut plugins = BTreeMap::new();
761 for plugin_info in protobuf_session_manifest.plugins.into_iter() {
762 let mut configuration = BTreeMap::new();
763 for context_item in plugin_info.plugin_config.into_iter() {
764 configuration.insert(context_item.name, context_item.value);
765 }
766 plugins.insert(
767 plugin_info.plugin_id,
768 PluginInfo {
769 location: plugin_info.plugin_url,
770 configuration,
771 },
772 );
773 }
774 Ok(SessionInfo {
775 name: protobuf_session_manifest.name,
776 tabs: protobuf_session_manifest
777 .tabs
778 .iter()
779 .filter_map(|t| t.clone().try_into().ok())
780 .collect(),
781 panes,
782 connected_clients: protobuf_session_manifest.connected_clients as usize,
783 is_current_session: protobuf_session_manifest.is_current_session,
784 available_layouts: protobuf_session_manifest
785 .available_layouts
786 .into_iter()
787 .filter_map(|l| LayoutInfo::try_from(l).ok())
788 .collect(),
789 plugins,
790 })
791 }
792}
793
794impl TryFrom<LayoutInfo> for ProtobufLayoutInfo {
795 type Error = &'static str;
796 fn try_from(layout_info: LayoutInfo) -> Result<Self, &'static str> {
797 match layout_info {
798 LayoutInfo::File(name) => Ok(ProtobufLayoutInfo {
799 source: "file".to_owned(),
800 name,
801 }),
802 LayoutInfo::BuiltIn(name) => Ok(ProtobufLayoutInfo {
803 source: "built-in".to_owned(),
804 name,
805 }),
806 LayoutInfo::Url(name) => Ok(ProtobufLayoutInfo {
807 source: "url".to_owned(),
808 name,
809 }),
810 LayoutInfo::Stringified(stringified_layout) => Ok(ProtobufLayoutInfo {
811 source: "stringified".to_owned(),
812 name: stringified_layout.clone(),
813 }),
814 }
815 }
816}
817
818impl TryFrom<ProtobufLayoutInfo> for LayoutInfo {
819 type Error = &'static str;
820 fn try_from(protobuf_layout_info: ProtobufLayoutInfo) -> Result<Self, &'static str> {
821 match protobuf_layout_info.source.as_str() {
822 "file" => Ok(LayoutInfo::File(protobuf_layout_info.name)),
823 "built-in" => Ok(LayoutInfo::BuiltIn(protobuf_layout_info.name)),
824 "url" => Ok(LayoutInfo::Url(protobuf_layout_info.name)),
825 "stringified" => Ok(LayoutInfo::Stringified(protobuf_layout_info.name)),
826 _ => Err("Unknown source for layout"),
827 }
828 }
829}
830
831impl TryFrom<CopyDestination> for ProtobufCopyDestination {
832 type Error = &'static str;
833 fn try_from(copy_destination: CopyDestination) -> Result<Self, &'static str> {
834 match copy_destination {
835 CopyDestination::Command => Ok(ProtobufCopyDestination::Command),
836 CopyDestination::Primary => Ok(ProtobufCopyDestination::Primary),
837 CopyDestination::System => Ok(ProtobufCopyDestination::System),
838 }
839 }
840}
841
842impl TryFrom<ProtobufCopyDestination> for CopyDestination {
843 type Error = &'static str;
844 fn try_from(protobuf_copy_destination: ProtobufCopyDestination) -> Result<Self, &'static str> {
845 match protobuf_copy_destination {
846 ProtobufCopyDestination::Command => Ok(CopyDestination::Command),
847 ProtobufCopyDestination::Primary => Ok(CopyDestination::Primary),
848 ProtobufCopyDestination::System => Ok(CopyDestination::System),
849 }
850 }
851}
852
853impl TryFrom<MouseEventPayload> for Mouse {
854 type Error = &'static str;
855 fn try_from(mouse_event_payload: MouseEventPayload) -> Result<Self, &'static str> {
856 match MouseEventName::from_i32(mouse_event_payload.mouse_event_name) {
857 Some(MouseEventName::MouseScrollUp) => match mouse_event_payload.mouse_event_payload {
858 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
859 Ok(Mouse::ScrollUp(line_count as usize))
860 },
861 _ => Err("Malformed payload for mouse scroll up"),
862 },
863 Some(MouseEventName::MouseScrollDown) => {
864 match mouse_event_payload.mouse_event_payload {
865 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
866 Ok(Mouse::ScrollDown(line_count as usize))
867 },
868 _ => Err("Malformed payload for mouse scroll down"),
869 }
870 },
871 Some(MouseEventName::MouseLeftClick) => match mouse_event_payload.mouse_event_payload {
872 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
873 Mouse::LeftClick(position.line as isize, position.column as usize),
874 ),
875 _ => Err("Malformed payload for mouse left click"),
876 },
877 Some(MouseEventName::MouseRightClick) => {
878 match mouse_event_payload.mouse_event_payload {
879 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
880 Mouse::RightClick(position.line as isize, position.column as usize),
881 ),
882 _ => Err("Malformed payload for mouse right click"),
883 }
884 },
885 Some(MouseEventName::MouseHold) => match mouse_event_payload.mouse_event_payload {
886 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
887 Mouse::Hold(position.line as isize, position.column as usize),
888 ),
889 _ => Err("Malformed payload for mouse hold"),
890 },
891 Some(MouseEventName::MouseRelease) => match mouse_event_payload.mouse_event_payload {
892 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
893 Mouse::Release(position.line as isize, position.column as usize),
894 ),
895 _ => Err("Malformed payload for mouse release"),
896 },
897 None => Err("Malformed payload for MouseEventName"),
898 }
899 }
900}
901
902impl TryFrom<Mouse> for MouseEventPayload {
903 type Error = &'static str;
904 fn try_from(mouse: Mouse) -> Result<Self, &'static str> {
905 match mouse {
906 Mouse::ScrollUp(number_of_lines) => Ok(MouseEventPayload {
907 mouse_event_name: MouseEventName::MouseScrollUp as i32,
908 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
909 number_of_lines as u32,
910 )),
911 }),
912 Mouse::ScrollDown(number_of_lines) => Ok(MouseEventPayload {
913 mouse_event_name: MouseEventName::MouseScrollDown as i32,
914 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
915 number_of_lines as u32,
916 )),
917 }),
918 Mouse::LeftClick(line, column) => Ok(MouseEventPayload {
919 mouse_event_name: MouseEventName::MouseLeftClick as i32,
920 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
921 ProtobufPosition {
922 line: line as i64,
923 column: column as i64,
924 },
925 )),
926 }),
927 Mouse::RightClick(line, column) => Ok(MouseEventPayload {
928 mouse_event_name: MouseEventName::MouseRightClick as i32,
929 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
930 ProtobufPosition {
931 line: line as i64,
932 column: column as i64,
933 },
934 )),
935 }),
936 Mouse::Hold(line, column) => Ok(MouseEventPayload {
937 mouse_event_name: MouseEventName::MouseHold as i32,
938 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
939 ProtobufPosition {
940 line: line as i64,
941 column: column as i64,
942 },
943 )),
944 }),
945 Mouse::Release(line, column) => Ok(MouseEventPayload {
946 mouse_event_name: MouseEventName::MouseRelease as i32,
947 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
948 ProtobufPosition {
949 line: line as i64,
950 column: column as i64,
951 },
952 )),
953 }),
954 }
955 }
956}
957
958impl TryFrom<ProtobufPaneInfo> for PaneInfo {
959 type Error = &'static str;
960 fn try_from(protobuf_pane_info: ProtobufPaneInfo) -> Result<Self, &'static str> {
961 Ok(PaneInfo {
962 id: protobuf_pane_info.id,
963 is_plugin: protobuf_pane_info.is_plugin,
964 is_focused: protobuf_pane_info.is_focused,
965 is_fullscreen: protobuf_pane_info.is_fullscreen,
966 is_floating: protobuf_pane_info.is_floating,
967 is_suppressed: protobuf_pane_info.is_suppressed,
968 title: protobuf_pane_info.title,
969 exited: protobuf_pane_info.exited,
970 exit_status: protobuf_pane_info.exit_status,
971 is_held: protobuf_pane_info.is_held,
972 pane_x: protobuf_pane_info.pane_x as usize,
973 pane_content_x: protobuf_pane_info.pane_content_x as usize,
974 pane_y: protobuf_pane_info.pane_y as usize,
975 pane_content_y: protobuf_pane_info.pane_content_y as usize,
976 pane_rows: protobuf_pane_info.pane_rows as usize,
977 pane_content_rows: protobuf_pane_info.pane_content_rows as usize,
978 pane_columns: protobuf_pane_info.pane_columns as usize,
979 pane_content_columns: protobuf_pane_info.pane_content_columns as usize,
980 cursor_coordinates_in_pane: protobuf_pane_info
981 .cursor_coordinates_in_pane
982 .map(|position| (position.column as usize, position.line as usize)),
983 terminal_command: protobuf_pane_info.terminal_command,
984 plugin_url: protobuf_pane_info.plugin_url,
985 is_selectable: protobuf_pane_info.is_selectable,
986 })
987 }
988}
989
990impl TryFrom<PaneInfo> for ProtobufPaneInfo {
991 type Error = &'static str;
992 fn try_from(pane_info: PaneInfo) -> Result<Self, &'static str> {
993 Ok(ProtobufPaneInfo {
994 id: pane_info.id,
995 is_plugin: pane_info.is_plugin,
996 is_focused: pane_info.is_focused,
997 is_fullscreen: pane_info.is_fullscreen,
998 is_floating: pane_info.is_floating,
999 is_suppressed: pane_info.is_suppressed,
1000 title: pane_info.title,
1001 exited: pane_info.exited,
1002 exit_status: pane_info.exit_status,
1003 is_held: pane_info.is_held,
1004 pane_x: pane_info.pane_x as u32,
1005 pane_content_x: pane_info.pane_content_x as u32,
1006 pane_y: pane_info.pane_y as u32,
1007 pane_content_y: pane_info.pane_content_y as u32,
1008 pane_rows: pane_info.pane_rows as u32,
1009 pane_content_rows: pane_info.pane_content_rows as u32,
1010 pane_columns: pane_info.pane_columns as u32,
1011 pane_content_columns: pane_info.pane_content_columns as u32,
1012 cursor_coordinates_in_pane: pane_info.cursor_coordinates_in_pane.map(|(x, y)| {
1013 ProtobufPosition {
1014 column: x as i64,
1015 line: y as i64,
1016 }
1017 }),
1018 terminal_command: pane_info.terminal_command,
1019 plugin_url: pane_info.plugin_url,
1020 is_selectable: pane_info.is_selectable,
1021 })
1022 }
1023}
1024
1025impl TryFrom<ProtobufTabInfo> for TabInfo {
1026 type Error = &'static str;
1027 fn try_from(protobuf_tab_info: ProtobufTabInfo) -> Result<Self, &'static str> {
1028 Ok(TabInfo {
1029 position: protobuf_tab_info.position as usize,
1030 name: protobuf_tab_info.name,
1031 active: protobuf_tab_info.active,
1032 panes_to_hide: protobuf_tab_info.panes_to_hide as usize,
1033 is_fullscreen_active: protobuf_tab_info.is_fullscreen_active,
1034 is_sync_panes_active: protobuf_tab_info.is_sync_panes_active,
1035 are_floating_panes_visible: protobuf_tab_info.are_floating_panes_visible,
1036 other_focused_clients: protobuf_tab_info
1037 .other_focused_clients
1038 .iter()
1039 .map(|c| *c as u16)
1040 .collect(),
1041 active_swap_layout_name: protobuf_tab_info.active_swap_layout_name,
1042 is_swap_layout_dirty: protobuf_tab_info.is_swap_layout_dirty,
1043 })
1044 }
1045}
1046
1047impl TryFrom<TabInfo> for ProtobufTabInfo {
1048 type Error = &'static str;
1049 fn try_from(tab_info: TabInfo) -> Result<Self, &'static str> {
1050 Ok(ProtobufTabInfo {
1051 position: tab_info.position as u32,
1052 name: tab_info.name,
1053 active: tab_info.active,
1054 panes_to_hide: tab_info.panes_to_hide as u32,
1055 is_fullscreen_active: tab_info.is_fullscreen_active,
1056 is_sync_panes_active: tab_info.is_sync_panes_active,
1057 are_floating_panes_visible: tab_info.are_floating_panes_visible,
1058 other_focused_clients: tab_info
1059 .other_focused_clients
1060 .iter()
1061 .map(|c| *c as u32)
1062 .collect(),
1063 active_swap_layout_name: tab_info.active_swap_layout_name,
1064 is_swap_layout_dirty: tab_info.is_swap_layout_dirty,
1065 })
1066 }
1067}
1068
1069impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
1070 type Error = &'static str;
1071 fn try_from(
1072 mut protobuf_mode_update_payload: ProtobufModeUpdatePayload,
1073 ) -> Result<Self, &'static str> {
1074 let current_mode: InputMode =
1075 ProtobufInputMode::from_i32(protobuf_mode_update_payload.current_mode)
1076 .ok_or("Malformed InputMode in the ModeUpdate Event")?
1077 .try_into()?;
1078 let base_mode: Option<InputMode> = protobuf_mode_update_payload
1079 .base_mode
1080 .and_then(|b_m| ProtobufInputMode::from_i32(b_m)?.try_into().ok());
1081 let keybinds: Vec<(InputMode, Vec<(KeyWithModifier, Vec<Action>)>)> =
1082 protobuf_mode_update_payload
1083 .keybinds
1084 .iter_mut()
1085 .filter_map(|k| {
1086 let input_mode: InputMode = ProtobufInputMode::from_i32(k.mode)
1087 .ok_or("Malformed InputMode in the ModeUpdate Event")
1088 .ok()?
1089 .try_into()
1090 .ok()?;
1091 let mut keybinds: Vec<(KeyWithModifier, Vec<Action>)> = vec![];
1092 for mut protobuf_keybind in k.key_bind.drain(..) {
1093 let key: KeyWithModifier = protobuf_keybind.key.unwrap().try_into().ok()?;
1094 let mut actions: Vec<Action> = vec![];
1095 for action in protobuf_keybind.action.drain(..) {
1096 if let Ok(action) = action.try_into() {
1097 actions.push(action);
1098 }
1099 }
1100 keybinds.push((key, actions));
1101 }
1102 Some((input_mode, keybinds))
1103 })
1104 .collect();
1105 let style: Style = protobuf_mode_update_payload
1106 .style
1107 .and_then(|m| m.try_into().ok())
1108 .ok_or("malformed payload for mode_info")?;
1109 let session_name = protobuf_mode_update_payload.session_name;
1110 let capabilities = PluginCapabilities {
1111 arrow_fonts: protobuf_mode_update_payload.arrow_fonts_support,
1112 };
1113 let mode_info = ModeInfo {
1114 mode: current_mode,
1115 keybinds,
1116 style,
1117 capabilities,
1118 session_name,
1119 base_mode,
1120 };
1121 Ok(mode_info)
1122 }
1123}
1124
1125impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
1126 type Error = &'static str;
1127 fn try_from(mode_info: ModeInfo) -> Result<Self, &'static str> {
1128 let current_mode: ProtobufInputMode = mode_info.mode.try_into()?;
1129 let base_mode: Option<ProtobufInputMode> = mode_info
1130 .base_mode
1131 .and_then(|mode| ProtobufInputMode::try_from(mode).ok());
1132 let style: ProtobufStyle = mode_info.style.try_into()?;
1133 let arrow_fonts_support: bool = mode_info.capabilities.arrow_fonts;
1134 let session_name = mode_info.session_name;
1135 let mut protobuf_input_mode_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
1136 for (input_mode, input_mode_keybinds) in mode_info.keybinds {
1137 let mode: ProtobufInputMode = input_mode.try_into()?;
1138 let mut keybinds: Vec<ProtobufKeyBind> = vec![];
1139 for (key, actions) in input_mode_keybinds {
1140 let protobuf_key: ProtobufKey = key.try_into()?;
1141 let mut protobuf_actions: Vec<ProtobufAction> = vec![];
1142 for action in actions {
1143 if let Ok(protobuf_action) = action.try_into() {
1144 protobuf_actions.push(protobuf_action);
1145 }
1146 }
1147 let key_bind = ProtobufKeyBind {
1148 key: Some(protobuf_key),
1149 action: protobuf_actions,
1150 };
1151 keybinds.push(key_bind);
1152 }
1153 let input_mode_keybind = ProtobufInputModeKeybinds {
1154 mode: mode as i32,
1155 key_bind: keybinds,
1156 };
1157 protobuf_input_mode_keybinds.push(input_mode_keybind);
1158 }
1159 Ok(ProtobufModeUpdatePayload {
1160 current_mode: current_mode as i32,
1161 style: Some(style),
1162 keybinds: protobuf_input_mode_keybinds,
1163 arrow_fonts_support,
1164 session_name,
1165 base_mode: base_mode.map(|b_m| b_m as i32),
1166 })
1167 }
1168}
1169
1170impl TryFrom<ProtobufEventNameList> for HashSet<EventType> {
1171 type Error = &'static str;
1172 fn try_from(protobuf_event_name_list: ProtobufEventNameList) -> Result<Self, &'static str> {
1173 let event_types: Vec<ProtobufEventType> = protobuf_event_name_list
1174 .event_types
1175 .iter()
1176 .filter_map(|i| ProtobufEventType::from_i32(*i))
1177 .collect();
1178 let event_types: Vec<EventType> = event_types
1179 .iter()
1180 .filter_map(|e| EventType::try_from(*e).ok())
1181 .collect();
1182 Ok(event_types.into_iter().collect())
1183 }
1184}
1185
1186impl TryFrom<HashSet<EventType>> for ProtobufEventNameList {
1187 type Error = &'static str;
1188 fn try_from(event_types: HashSet<EventType>) -> Result<Self, &'static str> {
1189 let protobuf_event_name_list = ProtobufEventNameList {
1190 event_types: event_types
1191 .iter()
1192 .filter_map(|e| ProtobufEventType::try_from(*e).ok())
1193 .map(|e| e as i32)
1194 .collect(),
1195 };
1196 Ok(protobuf_event_name_list)
1197 }
1198}
1199
1200impl TryFrom<ProtobufEventType> for EventType {
1201 type Error = &'static str;
1202 fn try_from(protobuf_event_type: ProtobufEventType) -> Result<Self, &'static str> {
1203 Ok(match protobuf_event_type {
1204 ProtobufEventType::ModeUpdate => EventType::ModeUpdate,
1205 ProtobufEventType::TabUpdate => EventType::TabUpdate,
1206 ProtobufEventType::PaneUpdate => EventType::PaneUpdate,
1207 ProtobufEventType::Key => EventType::Key,
1208 ProtobufEventType::Mouse => EventType::Mouse,
1209 ProtobufEventType::Timer => EventType::Timer,
1210 ProtobufEventType::CopyToClipboard => EventType::CopyToClipboard,
1211 ProtobufEventType::SystemClipboardFailure => EventType::SystemClipboardFailure,
1212 ProtobufEventType::InputReceived => EventType::InputReceived,
1213 ProtobufEventType::Visible => EventType::Visible,
1214 ProtobufEventType::CustomMessage => EventType::CustomMessage,
1215 ProtobufEventType::FileSystemCreate => EventType::FileSystemCreate,
1216 ProtobufEventType::FileSystemRead => EventType::FileSystemRead,
1217 ProtobufEventType::FileSystemUpdate => EventType::FileSystemUpdate,
1218 ProtobufEventType::FileSystemDelete => EventType::FileSystemDelete,
1219 ProtobufEventType::PermissionRequestResult => EventType::PermissionRequestResult,
1220 ProtobufEventType::SessionUpdate => EventType::SessionUpdate,
1221 ProtobufEventType::RunCommandResult => EventType::RunCommandResult,
1222 ProtobufEventType::WebRequestResult => EventType::WebRequestResult,
1223 ProtobufEventType::CommandPaneOpened => EventType::CommandPaneOpened,
1224 ProtobufEventType::CommandPaneExited => EventType::CommandPaneExited,
1225 ProtobufEventType::PaneClosed => EventType::PaneClosed,
1226 ProtobufEventType::EditPaneOpened => EventType::EditPaneOpened,
1227 ProtobufEventType::EditPaneExited => EventType::EditPaneExited,
1228 ProtobufEventType::CommandPaneReRun => EventType::CommandPaneReRun,
1229 ProtobufEventType::FailedToWriteConfigToDisk => EventType::FailedToWriteConfigToDisk,
1230 ProtobufEventType::ListClients => EventType::ListClients,
1231 })
1232 }
1233}
1234
1235impl TryFrom<EventType> for ProtobufEventType {
1236 type Error = &'static str;
1237 fn try_from(event_type: EventType) -> Result<Self, &'static str> {
1238 Ok(match event_type {
1239 EventType::ModeUpdate => ProtobufEventType::ModeUpdate,
1240 EventType::TabUpdate => ProtobufEventType::TabUpdate,
1241 EventType::PaneUpdate => ProtobufEventType::PaneUpdate,
1242 EventType::Key => ProtobufEventType::Key,
1243 EventType::Mouse => ProtobufEventType::Mouse,
1244 EventType::Timer => ProtobufEventType::Timer,
1245 EventType::CopyToClipboard => ProtobufEventType::CopyToClipboard,
1246 EventType::SystemClipboardFailure => ProtobufEventType::SystemClipboardFailure,
1247 EventType::InputReceived => ProtobufEventType::InputReceived,
1248 EventType::Visible => ProtobufEventType::Visible,
1249 EventType::CustomMessage => ProtobufEventType::CustomMessage,
1250 EventType::FileSystemCreate => ProtobufEventType::FileSystemCreate,
1251 EventType::FileSystemRead => ProtobufEventType::FileSystemRead,
1252 EventType::FileSystemUpdate => ProtobufEventType::FileSystemUpdate,
1253 EventType::FileSystemDelete => ProtobufEventType::FileSystemDelete,
1254 EventType::PermissionRequestResult => ProtobufEventType::PermissionRequestResult,
1255 EventType::SessionUpdate => ProtobufEventType::SessionUpdate,
1256 EventType::RunCommandResult => ProtobufEventType::RunCommandResult,
1257 EventType::WebRequestResult => ProtobufEventType::WebRequestResult,
1258 EventType::CommandPaneOpened => ProtobufEventType::CommandPaneOpened,
1259 EventType::CommandPaneExited => ProtobufEventType::CommandPaneExited,
1260 EventType::PaneClosed => ProtobufEventType::PaneClosed,
1261 EventType::EditPaneOpened => ProtobufEventType::EditPaneOpened,
1262 EventType::EditPaneExited => ProtobufEventType::EditPaneExited,
1263 EventType::CommandPaneReRun => ProtobufEventType::CommandPaneReRun,
1264 EventType::FailedToWriteConfigToDisk => ProtobufEventType::FailedToWriteConfigToDisk,
1265 EventType::ListClients => ProtobufEventType::ListClients,
1266 })
1267 }
1268}
1269
1270impl From<ProtobufResurrectableSession> for (String, Duration) {
1271 fn from(protobuf_resurrectable_session: ProtobufResurrectableSession) -> (String, Duration) {
1272 (
1273 protobuf_resurrectable_session.name,
1274 Duration::from_secs(protobuf_resurrectable_session.creation_time),
1275 )
1276 }
1277}
1278
1279impl From<(String, Duration)> for ProtobufResurrectableSession {
1280 fn from(session_name_and_creation_time: (String, Duration)) -> ProtobufResurrectableSession {
1281 ProtobufResurrectableSession {
1282 name: session_name_and_creation_time.0,
1283 creation_time: session_name_and_creation_time.1.as_secs(),
1284 }
1285 }
1286}
1287
1288impl From<&ProtobufFileMetadata> for Option<FileMetadata> {
1289 fn from(protobuf_file_metadata: &ProtobufFileMetadata) -> Option<FileMetadata> {
1290 if protobuf_file_metadata.metadata_is_set {
1291 Some(FileMetadata {
1292 is_file: protobuf_file_metadata.is_file,
1293 is_dir: protobuf_file_metadata.is_dir,
1294 is_symlink: protobuf_file_metadata.is_symlink,
1295 len: protobuf_file_metadata.len,
1296 })
1297 } else {
1298 None
1299 }
1300 }
1301}
1302
1303impl From<Option<FileMetadata>> for ProtobufFileMetadata {
1304 fn from(file_metadata: Option<FileMetadata>) -> ProtobufFileMetadata {
1305 match file_metadata {
1306 Some(file_metadata) => ProtobufFileMetadata {
1307 metadata_is_set: true,
1308 is_file: file_metadata.is_file,
1309 is_dir: file_metadata.is_dir,
1310 is_symlink: file_metadata.is_symlink,
1311 len: file_metadata.len,
1312 },
1313 None => ProtobufFileMetadata {
1314 metadata_is_set: false,
1315 ..Default::default()
1316 },
1317 }
1318 }
1319}
1320
1321#[test]
1322fn serialize_mode_update_event() {
1323 use prost::Message;
1324 let mode_update_event = Event::ModeUpdate(Default::default());
1325 let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
1326 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1327 let deserialized_protobuf_event: ProtobufEvent =
1328 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1329 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1330 assert_eq!(
1331 mode_update_event, deserialized_event,
1332 "Event properly serialized/deserialized without change"
1333 );
1334}
1335
1336#[test]
1337fn serialize_mode_update_event_with_non_default_values() {
1338 use crate::data::{BareKey, Palette, PaletteColor, ThemeHue};
1339 use prost::Message;
1340 let mode_update_event = Event::ModeUpdate(ModeInfo {
1341 mode: InputMode::Locked,
1342 keybinds: vec![
1343 (
1344 InputMode::Locked,
1345 vec![(
1346 KeyWithModifier::new(BareKey::Char('b')).with_alt_modifier(),
1347 vec![Action::SwitchToMode(InputMode::Normal)],
1348 )],
1349 ),
1350 (
1351 InputMode::Tab,
1352 vec![(
1353 KeyWithModifier::new(BareKey::Up).with_alt_modifier(),
1354 vec![Action::SwitchToMode(InputMode::Pane)],
1355 )],
1356 ),
1357 (
1358 InputMode::Pane,
1359 vec![
1360 (
1361 KeyWithModifier::new(BareKey::Char('b')).with_ctrl_modifier(),
1362 vec![
1363 Action::SwitchToMode(InputMode::Tmux),
1364 Action::Write(None, vec![10], false),
1365 ],
1366 ),
1367 (
1368 KeyWithModifier::new(BareKey::Char('a')),
1369 vec![Action::WriteChars("foo".to_owned())],
1370 ),
1371 ],
1372 ),
1373 ],
1374 style: Style {
1375 colors: Palette {
1376 source: crate::data::PaletteSource::Default,
1377 theme_hue: ThemeHue::Light,
1378 fg: PaletteColor::Rgb((1, 1, 1)),
1379 bg: PaletteColor::Rgb((200, 200, 200)),
1380 black: PaletteColor::EightBit(1),
1381 red: PaletteColor::EightBit(2),
1382 green: PaletteColor::EightBit(2),
1383 yellow: PaletteColor::EightBit(2),
1384 blue: PaletteColor::EightBit(2),
1385 magenta: PaletteColor::EightBit(2),
1386 cyan: PaletteColor::EightBit(2),
1387 white: PaletteColor::EightBit(2),
1388 orange: PaletteColor::EightBit(2),
1389 gray: PaletteColor::EightBit(2),
1390 purple: PaletteColor::EightBit(2),
1391 gold: PaletteColor::EightBit(2),
1392 silver: PaletteColor::EightBit(2),
1393 pink: PaletteColor::EightBit(2),
1394 brown: PaletteColor::Rgb((222, 221, 220)),
1395 },
1396 rounded_corners: true,
1397 hide_session_name: false,
1398 },
1399 capabilities: PluginCapabilities { arrow_fonts: false },
1400 session_name: Some("my awesome test session".to_owned()),
1401 base_mode: Some(InputMode::Locked),
1402 });
1403 let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
1404 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1405 let deserialized_protobuf_event: ProtobufEvent =
1406 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1407 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1408 assert_eq!(
1409 mode_update_event, deserialized_event,
1410 "Event properly serialized/deserialized without change"
1411 );
1412}
1413
1414#[test]
1415fn serialize_tab_update_event() {
1416 use prost::Message;
1417 let tab_update_event = Event::TabUpdate(Default::default());
1418 let protobuf_event: ProtobufEvent = tab_update_event.clone().try_into().unwrap();
1419 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1420 let deserialized_protobuf_event: ProtobufEvent =
1421 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1422 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1423 assert_eq!(
1424 tab_update_event, deserialized_event,
1425 "Event properly serialized/deserialized without change"
1426 );
1427}
1428
1429#[test]
1430fn serialize_tab_update_event_with_non_default_values() {
1431 use prost::Message;
1432 let tab_update_event = Event::TabUpdate(vec![
1433 TabInfo {
1434 position: 0,
1435 name: "First tab".to_owned(),
1436 active: true,
1437 panes_to_hide: 2,
1438 is_fullscreen_active: true,
1439 is_sync_panes_active: false,
1440 are_floating_panes_visible: true,
1441 other_focused_clients: vec![2, 3, 4],
1442 active_swap_layout_name: Some("my cool swap layout".to_owned()),
1443 is_swap_layout_dirty: false,
1444 },
1445 TabInfo {
1446 position: 1,
1447 name: "Secondtab".to_owned(),
1448 active: false,
1449 panes_to_hide: 5,
1450 is_fullscreen_active: false,
1451 is_sync_panes_active: true,
1452 are_floating_panes_visible: true,
1453 other_focused_clients: vec![1, 5, 111],
1454 active_swap_layout_name: None,
1455 is_swap_layout_dirty: true,
1456 },
1457 TabInfo::default(),
1458 ]);
1459 let protobuf_event: ProtobufEvent = tab_update_event.clone().try_into().unwrap();
1460 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1461 let deserialized_protobuf_event: ProtobufEvent =
1462 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1463 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1464 assert_eq!(
1465 tab_update_event, deserialized_event,
1466 "Event properly serialized/deserialized without change"
1467 );
1468}
1469
1470#[test]
1471fn serialize_pane_update_event() {
1472 use prost::Message;
1473 let pane_update_event = Event::PaneUpdate(Default::default());
1474 let protobuf_event: ProtobufEvent = pane_update_event.clone().try_into().unwrap();
1475 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1476 let deserialized_protobuf_event: ProtobufEvent =
1477 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1478 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1479 assert_eq!(
1480 pane_update_event, deserialized_event,
1481 "Event properly serialized/deserialized without change"
1482 );
1483}
1484
1485#[test]
1486fn serialize_key_event() {
1487 use crate::data::BareKey;
1488 use prost::Message;
1489 let key_event = Event::Key(KeyWithModifier::new(BareKey::Char('a')).with_ctrl_modifier());
1490 let protobuf_event: ProtobufEvent = key_event.clone().try_into().unwrap();
1491 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1492 let deserialized_protobuf_event: ProtobufEvent =
1493 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1494 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1495 assert_eq!(
1496 key_event, deserialized_event,
1497 "Event properly serialized/deserialized without change"
1498 );
1499}
1500
1501#[test]
1502fn serialize_mouse_event() {
1503 use prost::Message;
1504 let mouse_event = Event::Mouse(Mouse::LeftClick(1, 1));
1505 let protobuf_event: ProtobufEvent = mouse_event.clone().try_into().unwrap();
1506 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1507 let deserialized_protobuf_event: ProtobufEvent =
1508 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1509 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1510 assert_eq!(
1511 mouse_event, deserialized_event,
1512 "Event properly serialized/deserialized without change"
1513 );
1514}
1515
1516#[test]
1517fn serialize_mouse_event_without_position() {
1518 use prost::Message;
1519 let mouse_event = Event::Mouse(Mouse::ScrollUp(17));
1520 let protobuf_event: ProtobufEvent = mouse_event.clone().try_into().unwrap();
1521 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1522 let deserialized_protobuf_event: ProtobufEvent =
1523 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1524 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1525 assert_eq!(
1526 mouse_event, deserialized_event,
1527 "Event properly serialized/deserialized without change"
1528 );
1529}
1530
1531#[test]
1532fn serialize_timer_event() {
1533 use prost::Message;
1534 let timer_event = Event::Timer(1.5);
1535 let protobuf_event: ProtobufEvent = timer_event.clone().try_into().unwrap();
1536 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1537 let deserialized_protobuf_event: ProtobufEvent =
1538 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1539 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1540 assert_eq!(
1541 timer_event, deserialized_event,
1542 "Event properly serialized/deserialized without change"
1543 );
1544}
1545
1546#[test]
1547fn serialize_copy_to_clipboard_event() {
1548 use prost::Message;
1549 let copy_event = Event::CopyToClipboard(CopyDestination::Primary);
1550 let protobuf_event: ProtobufEvent = copy_event.clone().try_into().unwrap();
1551 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1552 let deserialized_protobuf_event: ProtobufEvent =
1553 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1554 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1555 assert_eq!(
1556 copy_event, deserialized_event,
1557 "Event properly serialized/deserialized without change"
1558 );
1559}
1560
1561#[test]
1562fn serialize_clipboard_failure_event() {
1563 use prost::Message;
1564 let copy_event = Event::SystemClipboardFailure;
1565 let protobuf_event: ProtobufEvent = copy_event.clone().try_into().unwrap();
1566 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1567 let deserialized_protobuf_event: ProtobufEvent =
1568 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1569 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1570 assert_eq!(
1571 copy_event, deserialized_event,
1572 "Event properly serialized/deserialized without change"
1573 );
1574}
1575
1576#[test]
1577fn serialize_input_received_event() {
1578 use prost::Message;
1579 let input_received_event = Event::InputReceived;
1580 let protobuf_event: ProtobufEvent = input_received_event.clone().try_into().unwrap();
1581 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1582 let deserialized_protobuf_event: ProtobufEvent =
1583 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1584 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1585 assert_eq!(
1586 input_received_event, deserialized_event,
1587 "Event properly serialized/deserialized without change"
1588 );
1589}
1590
1591#[test]
1592fn serialize_visible_event() {
1593 use prost::Message;
1594 let visible_event = Event::Visible(true);
1595 let protobuf_event: ProtobufEvent = visible_event.clone().try_into().unwrap();
1596 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1597 let deserialized_protobuf_event: ProtobufEvent =
1598 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1599 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1600 assert_eq!(
1601 visible_event, deserialized_event,
1602 "Event properly serialized/deserialized without change"
1603 );
1604}
1605
1606#[test]
1607fn serialize_custom_message_event() {
1608 use prost::Message;
1609 let custom_message_event = Event::CustomMessage("foo".to_owned(), "bar".to_owned());
1610 let protobuf_event: ProtobufEvent = custom_message_event.clone().try_into().unwrap();
1611 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1612 let deserialized_protobuf_event: ProtobufEvent =
1613 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1614 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1615 assert_eq!(
1616 custom_message_event, deserialized_event,
1617 "Event properly serialized/deserialized without change"
1618 );
1619}
1620
1621#[test]
1622fn serialize_file_system_create_event() {
1623 use prost::Message;
1624 let file_system_event = Event::FileSystemCreate(vec![
1625 ("/absolute/path".into(), None),
1626 ("./relative_path".into(), Default::default()),
1627 ]);
1628 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
1629 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1630 let deserialized_protobuf_event: ProtobufEvent =
1631 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1632 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1633 assert_eq!(
1634 file_system_event, deserialized_event,
1635 "Event properly serialized/deserialized without change"
1636 );
1637}
1638
1639#[test]
1640fn serialize_file_system_read_event() {
1641 use prost::Message;
1642 let file_system_event = Event::FileSystemRead(vec![
1643 ("/absolute/path".into(), None),
1644 ("./relative_path".into(), Default::default()),
1645 ]);
1646 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
1647 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1648 let deserialized_protobuf_event: ProtobufEvent =
1649 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1650 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1651 assert_eq!(
1652 file_system_event, deserialized_event,
1653 "Event properly serialized/deserialized without change"
1654 );
1655}
1656
1657#[test]
1658fn serialize_file_system_update_event() {
1659 use prost::Message;
1660 let file_system_event = Event::FileSystemUpdate(vec![
1661 ("/absolute/path".into(), None),
1662 ("./relative_path".into(), Some(Default::default())),
1663 ]);
1664 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
1665 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1666 let deserialized_protobuf_event: ProtobufEvent =
1667 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1668 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1669 assert_eq!(
1670 file_system_event, deserialized_event,
1671 "Event properly serialized/deserialized without change"
1672 );
1673}
1674
1675#[test]
1676fn serialize_file_system_delete_event() {
1677 use prost::Message;
1678 let file_system_event = Event::FileSystemDelete(vec![
1679 ("/absolute/path".into(), None),
1680 ("./relative_path".into(), Default::default()),
1681 ]);
1682 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
1683 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1684 let deserialized_protobuf_event: ProtobufEvent =
1685 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1686 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1687 assert_eq!(
1688 file_system_event, deserialized_event,
1689 "Event properly serialized/deserialized without change"
1690 );
1691}
1692
1693#[test]
1694fn serialize_session_update_event() {
1695 use prost::Message;
1696 let session_update_event = Event::SessionUpdate(Default::default(), Default::default());
1697 let protobuf_event: ProtobufEvent = session_update_event.clone().try_into().unwrap();
1698 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1699 let deserialized_protobuf_event: ProtobufEvent =
1700 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1701 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1702 assert_eq!(
1703 session_update_event, deserialized_event,
1704 "Event properly serialized/deserialized without change"
1705 );
1706}
1707
1708#[test]
1709fn serialize_session_update_event_with_non_default_values() {
1710 use prost::Message;
1711 let tab_infos = vec![
1712 TabInfo {
1713 position: 0,
1714 name: "First tab".to_owned(),
1715 active: true,
1716 panes_to_hide: 2,
1717 is_fullscreen_active: true,
1718 is_sync_panes_active: false,
1719 are_floating_panes_visible: true,
1720 other_focused_clients: vec![2, 3, 4],
1721 active_swap_layout_name: Some("my cool swap layout".to_owned()),
1722 is_swap_layout_dirty: false,
1723 },
1724 TabInfo {
1725 position: 1,
1726 name: "Secondtab".to_owned(),
1727 active: false,
1728 panes_to_hide: 5,
1729 is_fullscreen_active: false,
1730 is_sync_panes_active: true,
1731 are_floating_panes_visible: true,
1732 other_focused_clients: vec![1, 5, 111],
1733 active_swap_layout_name: None,
1734 is_swap_layout_dirty: true,
1735 },
1736 TabInfo::default(),
1737 ];
1738 let mut panes = HashMap::new();
1739 let panes_list = vec![
1740 PaneInfo {
1741 id: 1,
1742 is_plugin: false,
1743 is_focused: true,
1744 is_fullscreen: true,
1745 is_floating: false,
1746 is_suppressed: false,
1747 title: "pane 1".to_owned(),
1748 exited: false,
1749 exit_status: None,
1750 is_held: false,
1751 pane_x: 0,
1752 pane_content_x: 1,
1753 pane_y: 0,
1754 pane_content_y: 1,
1755 pane_rows: 5,
1756 pane_content_rows: 4,
1757 pane_columns: 22,
1758 pane_content_columns: 21,
1759 cursor_coordinates_in_pane: Some((0, 0)),
1760 terminal_command: Some("foo".to_owned()),
1761 plugin_url: None,
1762 is_selectable: true,
1763 },
1764 PaneInfo {
1765 id: 1,
1766 is_plugin: true,
1767 is_focused: true,
1768 is_fullscreen: true,
1769 is_floating: false,
1770 is_suppressed: false,
1771 title: "pane 1".to_owned(),
1772 exited: false,
1773 exit_status: None,
1774 is_held: false,
1775 pane_x: 0,
1776 pane_content_x: 1,
1777 pane_y: 0,
1778 pane_content_y: 1,
1779 pane_rows: 5,
1780 pane_content_rows: 4,
1781 pane_columns: 22,
1782 pane_content_columns: 21,
1783 cursor_coordinates_in_pane: Some((0, 0)),
1784 terminal_command: None,
1785 plugin_url: Some("i_am_a_fake_plugin".to_owned()),
1786 is_selectable: true,
1787 },
1788 ];
1789 panes.insert(0, panes_list);
1790 let mut plugins = BTreeMap::new();
1791 let mut plugin_configuration = BTreeMap::new();
1792 plugin_configuration.insert("config_key".to_owned(), "config_value".to_owned());
1793 plugins.insert(
1794 1,
1795 PluginInfo {
1796 location: "https://example.com/my-plugin.wasm".to_owned(),
1797 configuration: plugin_configuration,
1798 },
1799 );
1800 let session_info_1 = SessionInfo {
1801 name: "session 1".to_owned(),
1802 tabs: tab_infos,
1803 panes: PaneManifest { panes },
1804 connected_clients: 2,
1805 is_current_session: true,
1806 available_layouts: vec![
1807 LayoutInfo::File("layout 1".to_owned()),
1808 LayoutInfo::BuiltIn("layout2".to_owned()),
1809 LayoutInfo::File("layout3".to_owned()),
1810 ],
1811 plugins,
1812 };
1813 let session_info_2 = SessionInfo {
1814 name: "session 2".to_owned(),
1815 tabs: vec![],
1816 panes: PaneManifest {
1817 panes: HashMap::new(),
1818 },
1819 connected_clients: 0,
1820 is_current_session: false,
1821 available_layouts: vec![
1822 LayoutInfo::File("layout 1".to_owned()),
1823 LayoutInfo::BuiltIn("layout2".to_owned()),
1824 LayoutInfo::File("layout3".to_owned()),
1825 ],
1826 plugins: Default::default(),
1827 };
1828 let session_infos = vec![session_info_1, session_info_2];
1829 let resurrectable_sessions = vec![];
1830
1831 let session_update_event = Event::SessionUpdate(session_infos, resurrectable_sessions);
1832 let protobuf_event: ProtobufEvent = session_update_event.clone().try_into().unwrap();
1833 let serialized_protobuf_event = protobuf_event.encode_to_vec();
1834 let deserialized_protobuf_event: ProtobufEvent =
1835 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
1836 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
1837 assert_eq!(
1838 session_update_event, deserialized_event,
1839 "Event properly serialized/deserialized without change"
1840 );
1841}
1842
1843impl TryFrom<ProtobufPaneId> for PaneId {
1847 type Error = &'static str;
1848 fn try_from(protobuf_pane_id: ProtobufPaneId) -> Result<Self, &'static str> {
1849 match ProtobufPaneType::from_i32(protobuf_pane_id.pane_type) {
1850 Some(ProtobufPaneType::Terminal) => Ok(PaneId::Terminal(protobuf_pane_id.id)),
1851 Some(ProtobufPaneType::Plugin) => Ok(PaneId::Plugin(protobuf_pane_id.id)),
1852 None => Err("Failed to convert PaneId"),
1853 }
1854 }
1855}
1856
1857impl TryFrom<PaneId> for ProtobufPaneId {
1861 type Error = &'static str;
1862 fn try_from(pane_id: PaneId) -> Result<Self, &'static str> {
1863 match pane_id {
1864 PaneId::Terminal(id) => Ok(ProtobufPaneId {
1865 pane_type: ProtobufPaneType::Terminal as i32,
1866 id,
1867 }),
1868 PaneId::Plugin(id) => Ok(ProtobufPaneId {
1869 pane_type: ProtobufPaneType::Plugin as i32,
1870 id,
1871 }),
1872 }
1873 }
1874}