terrazzo-terminal 0.2.7

A simple web-based terminal emulator built on Terrazzo.
use std::time::Duration;

use nameth::NamedEnumValues as _;
use nameth::nameth;
use terrazzo::http::StatusCode;
use terrazzo_pty::ProcessInput;
use terrazzo_pty::pty::PtyError;
use terrazzo_pty::size::Size;
use tracing::debug;
use trz_gateway_common::http_error::IsHttpError;

use super::get_processes;
use crate::terminal_id::TerminalId;

pub async fn resize(
    terminal_id: &TerminalId,
    rows: i32,
    cols: i32,
    force: bool,
) -> Result<(), ResizeError> {
    debug!(rows, cols, "Size");
    let processes = get_processes();
    let entry = {
        let Some(entry) = processes.get(terminal_id) else {
            return Err(ResizeError::TerminalNotFound {
                terminal_id: terminal_id.clone(),
            });
        };
        entry.value().1.clone()
    };
    let input = entry.input().await;
    let ProcessInput(input) = &*input;
    if force {
        debug!("Forcing resize");
        let () = input
            .resize(Size::new(rows as u16 - 1, cols as u16 - 1))
            .map_err(ResizeError::Resize)?;
        tokio::time::sleep(Duration::from_millis(50)).await;
    }
    let () = input
        .resize(Size::new(rows as u16, cols as u16))
        .map_err(ResizeError::Resize)?;
    debug!("Done");
    Ok(())
}

#[nameth]
#[derive(thiserror::Error, Debug)]
pub enum ResizeError {
    #[error("[{n}] Failed to resize: {0}", n = self.name())]
    Resize(PtyError),

    #[error("[{n}] Terminal not found {terminal_id}", n = self.name())]
    TerminalNotFound { terminal_id: TerminalId },
}

impl IsHttpError for ResizeError {
    fn status_code(&self) -> StatusCode {
        match self {
            Self::Resize { .. } => StatusCode::INTERNAL_SERVER_ERROR,
            Self::TerminalNotFound { .. } => StatusCode::NOT_FOUND,
        }
    }
}