1use crate::errors::LitError;
2use crate::response::{CommandResponse, OutputFormat};
3use serde::Serialize;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Format {
8 Json,
9 JsonPretty,
10 Human,
11 MsgPack,
12}
13
14impl Format {
15 pub fn resolve(json: bool, human: bool, output: Option<&str>, pretty: bool) -> Self {
20 if human {
21 return Format::Human;
22 }
23 if json {
24 return if pretty {
25 Format::JsonPretty
26 } else {
27 Format::Json
28 };
29 }
30 if let Some(fmt) = output {
31 return match fmt {
32 "human" | "text" => Format::Human,
33 "msgpack" => Format::MsgPack,
34 "json-pretty" | "pretty" => Format::JsonPretty,
35 _ if pretty => Format::JsonPretty,
36 _ => Format::Json,
37 };
38 }
39 match std::env::var("LIT_OUTPUT").as_deref() {
40 Ok("human") | Ok("text") => Format::Human,
41 Ok("msgpack") => Format::MsgPack,
42 Ok("json-pretty") | Ok("pretty") => Format::JsonPretty,
43 _ if pretty => Format::JsonPretty,
44 _ => Format::Json,
45 }
46 }
47
48 pub fn to_output_format(self) -> OutputFormat {
50 match self {
51 Format::Json | Format::JsonPretty | Format::MsgPack => OutputFormat::Json,
52 Format::Human => OutputFormat::Human,
53 }
54 }
55}
56
57pub fn format_response<R: CommandResponse + Serialize>(response: &R, format: Format) -> Vec<u8> {
59 match format {
60 Format::Json => response.to_json_output().into_bytes(),
61 Format::JsonPretty => response.to_json_output_pretty().into_bytes(),
62 Format::Human => response.human_readable().into_bytes(),
63 Format::MsgPack => {
64 let data = serde_json::to_value(response).unwrap_or(serde_json::Value::Null);
65 let envelope = MsgPackEnvelope {
66 status: "ok",
67 command: response.command_name(),
68 data,
69 };
70 rmp_serde::to_vec(&envelope).unwrap_or_default()
71 }
72 }
73}
74
75pub fn format_error(error: &LitError, command: &str, format: Format) -> Vec<u8> {
77 let err_obj = serde_json::json!({
78 "status": "error",
79 "command": command,
80 "error": {
81 "code": error.error_code(),
82 "message": error.user_message(),
83 "suggestions": error.suggestions(),
84 }
85 });
86
87 match format {
88 Format::Json => serde_json::to_string(&err_obj)
89 .unwrap_or_default()
90 .into_bytes(),
91 Format::JsonPretty => serde_json::to_string_pretty(&err_obj)
92 .unwrap_or_default()
93 .into_bytes(),
94 Format::Human => {
95 let mut out = format!("error: {}", error.user_message());
96 let suggestions = error.suggestions();
97 if !suggestions.is_empty() {
98 out.push_str("\n\nhint:");
99 for s in suggestions {
100 out.push_str(&format!("\n {}", s));
101 }
102 }
103 out.into_bytes()
104 }
105 Format::MsgPack => rmp_serde::to_vec(&err_obj).unwrap_or_default(),
106 }
107}
108
109#[derive(Serialize)]
111struct MsgPackEnvelope<'a> {
112 status: &'a str,
113 command: &'a str,
114 data: serde_json::Value,
115}