Skip to main content

lilo_rm_core/
capture.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
7#[serde(tag = "type", content = "payload", rename_all = "snake_case")]
8pub enum LogAvailability {
9    Headless {
10        stdout_path: PathBuf,
11        stderr_path: PathBuf,
12    },
13    TmuxPaneSnapshot,
14    Unavailable {
15        reason: LogsUnavailableReason,
16    },
17}
18
19#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
20#[serde(rename_all = "snake_case")]
21pub enum LogsUnavailableReason {
22    TmuxTarget,
23    CaptureDisabled,
24    PaneUnavailable,
25    PipeInUse,
26    RecorderFailed,
27}
28
29impl LogsUnavailableReason {
30    pub const fn as_str(self) -> &'static str {
31        match self {
32            Self::TmuxTarget => "tmux_target",
33            Self::CaptureDisabled => "capture_disabled",
34            Self::PaneUnavailable => "pane_unavailable",
35            Self::PipeInUse => "pipe_in_use",
36            Self::RecorderFailed => "recorder_failed",
37        }
38    }
39}
40
41#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
42pub struct CaptureRequest {
43    pub session_id: Uuid,
44    #[serde(default, skip_serializing_if = "Option::is_none")]
45    pub scrollback_lines: Option<u32>,
46}
47
48#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
49pub struct PaneSnapshot {
50    pub content: String,
51    pub captured_at_ms: u64,
52    pub scrollback_lines_requested: u32,
53    pub scrollback_lines_included: u32,
54    pub pane_history_lines: u32,
55}
56
57#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
58#[non_exhaustive]
59#[serde(tag = "type", content = "payload", rename_all = "snake_case")]
60pub enum CaptureError {
61    NotATmuxTarget,
62    PaneUnavailable,
63    SessionMissing,
64    TmuxNotAvailable,
65    CapturePaneFailed { stderr: String },
66}
67
68#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
69#[non_exhaustive]
70#[serde(tag = "status", content = "payload", rename_all = "snake_case")]
71pub enum CaptureResponse {
72    Captured(PaneSnapshot),
73    Failed(CaptureError),
74}
75
76impl CaptureResponse {
77    pub fn into_result(self) -> Result<PaneSnapshot, CaptureError> {
78        match self {
79            Self::Captured(snapshot) => Ok(snapshot),
80            Self::Failed(error) => Err(error),
81        }
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::LogsUnavailableReason;
88
89    #[test]
90    fn logs_unavailable_reason_as_str_matches_serde_snake_case() {
91        assert_eq!(LogsUnavailableReason::TmuxTarget.as_str(), "tmux_target");
92        assert_eq!(
93            LogsUnavailableReason::CaptureDisabled.as_str(),
94            "capture_disabled"
95        );
96        assert_eq!(
97            LogsUnavailableReason::PaneUnavailable.as_str(),
98            "pane_unavailable"
99        );
100        assert_eq!(LogsUnavailableReason::PipeInUse.as_str(), "pipe_in_use");
101        assert_eq!(
102            LogsUnavailableReason::RecorderFailed.as_str(),
103            "recorder_failed"
104        );
105    }
106}