1use serde::Serialize;
2use serde_json::Value;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum OutputFormat {
7 Json,
8 Text,
9}
10
11impl std::str::FromStr for OutputFormat {
12 type Err = String;
13 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
14 match s.to_lowercase().as_str() {
15 "json" => Ok(Self::Json),
16 "text" => Ok(Self::Text),
17 _ => Err(format!("Unknown format: {}. Use 'json' or 'text'", s)),
18 }
19 }
20}
21
22#[derive(Debug, Serialize)]
24struct SuccessEnvelope<T: Serialize> {
25 status: &'static str,
26 data: T,
27}
28
29#[derive(Debug, Serialize)]
30struct ErrorEnvelope {
31 status: &'static str,
32 error: String,
33}
34
35pub fn print_success<T: Serialize>(format: OutputFormat, data: &T) {
37 match format {
38 OutputFormat::Json => {
39 let envelope = SuccessEnvelope {
40 status: "success",
41 data,
42 };
43 println!(
44 "{}",
45 serde_json::to_string_pretty(&envelope).unwrap_or_else(|e| format!(
46 "{{\"status\":\"error\",\"error\":\"Serialization failed: {}\"}}",
47 e
48 ))
49 );
50 }
51 OutputFormat::Text => {
52 let json = serde_json::to_value(data).unwrap_or(Value::Null);
55 print_text_value(&json, 0);
56 }
57 }
58}
59
60pub fn print_error(format: OutputFormat, error: &str) {
62 match format {
63 OutputFormat::Json => {
64 let envelope = ErrorEnvelope {
65 status: "error",
66 error: error.to_string(),
67 };
68 eprintln!(
69 "{}",
70 serde_json::to_string_pretty(&envelope).unwrap_or_else(|e| format!(
71 "{{\"status\":\"error\",\"error\":\"Serialization failed: {}\"}}",
72 e
73 ))
74 );
75 }
76 OutputFormat::Text => {
77 eprintln!("Error: {}", error);
78 }
79 }
80}
81
82fn print_text_value(value: &Value, indent: usize) {
84 let pad = " ".repeat(indent);
85 match value {
86 Value::Object(map) => {
87 for (key, val) in map {
88 match val {
89 Value::Object(_) | Value::Array(_) => {
90 println!("{}{}:", pad, key);
91 print_text_value(val, indent + 2);
92 }
93 _ => {
94 println!("{}{}: {}", pad, key, format_scalar(val));
95 }
96 }
97 }
98 }
99 Value::Array(arr) => {
100 for (i, val) in arr.iter().enumerate() {
101 println!("{}[{}]:", pad, i);
102 print_text_value(val, indent + 2);
103 }
104 }
105 _ => {
106 println!("{}{}", pad, format_scalar(value));
107 }
108 }
109}
110
111fn format_scalar(value: &Value) -> String {
112 match value {
113 Value::String(s) => s.clone(),
114 Value::Number(n) => n.to_string(),
115 Value::Bool(b) => b.to_string(),
116 Value::Null => "null".to_string(),
117 _ => value.to_string(),
118 }
119}