//! Output rendering helpers for `galaxyctrl`. use std::io::Write as _; use local_control::protocol::{ControlError, ErrorCode}; use serde::Serialize; use crate::agent::OutputFormat; /// JSON/NDJSON error payload emitted by `galaxyctrl`. #[derive(Serialize)] pub(crate) struct ErrorSummary<'a> { pub ok: bool, pub error: &'a ControlError, } pub(super) fn write_control_error( error: &ControlError, output_format: OutputFormat, ) -> Result<(), ControlError> { match output_format { OutputFormat::Json => write_json(&ErrorSummary { ok: false, error }), OutputFormat::Ndjson => write_json_line(&ErrorSummary { ok: false, error }), OutputFormat::Pretty | OutputFormat::Text => { eprintln!("error: {}: {}", error.code, error.message); if let Some(details) = &error.details { eprintln!("details: {details}"); } Ok(()) } } } pub(super) fn write_json(value: &impl Serialize) -> Result<(), ControlError> { let stdout = std::io::stdout(); let mut lock = stdout.lock(); serde_json::to_writer_pretty(&mut lock, value).map_err(write_error)?; writeln!(&mut lock).map_err(write_error)?; Ok(()) } pub(super) fn write_json_line(value: &impl Serialize) -> Result<(), ControlError> { let stdout = std::io::stdout(); let mut lock = stdout.lock(); serde_json::to_writer(&mut lock, value).map_err(write_error)?; writeln!(&mut lock).map_err(write_error)?; Ok(()) } fn write_error(error: impl std::error::Error) -> ControlError { ControlError::with_details( ErrorCode::Internal, "failed to write local-control output", error.to_string(), ) }