1use std::collections::HashMap;
2use std::fmt;
3
4use rfc3986::Rfc3986;
5use serde::Serialize;
6use serde_json as json;
7
8mod account;
9mod dynamo;
10mod ebs;
11mod ec2;
12mod eks;
13mod iam;
14mod pricing;
15mod rfc3986;
16mod s3;
17mod smithy;
18mod sso;
19mod sts;
20
21pub trait Show: fmt::Debug {
22 fn _fmt(&self) -> Box<dyn fmt::Display + '_>;
23
24 fn _fmt_compact(&self) -> Box<dyn fmt::Display + '_> {
25 self._fmt()
26 }
27
28 fn text(&self) -> String {
29 self._fmt().to_string()
30 }
31
32 fn debug(&self) -> String {
33 fmtools::format!({self:?})
34 }
35
36 fn json(&self) -> String {
37 "JSON view is not implemented yet".to_string()
38 }
39
40 fn table(&self) -> String {
41 "Table view is not implemented yet".to_string()
42 }
43
44 fn yaml(&self) -> String {
45 "YAML view is not implemented yet".to_string()
46 }
47
48 fn yaml_stream(&self) -> String {
49 "YAML stream view is not implemented yet".to_string()
50 }
51}
52
53impl<T: Show> Show for &T {
54 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
55 (*self)._fmt()
56 }
57
58 fn debug(&self) -> String {
59 (*self).debug()
60 }
61
62 fn json(&self) -> String {
63 (*self).json()
64 }
65
66 fn table(&self) -> String {
67 (*self).table()
68 }
69
70 fn yaml(&self) -> String {
71 (*self).yaml()
72 }
73
74 fn yaml_stream(&self) -> String {
75 (*self).yaml_stream()
76 }
77}
78
79impl<T: Show> Show for Vec<T> {
80 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
81 Box::new(fmtools::join("\n", self.iter().map(|item| item._fmt())))
82 }
83
84 fn debug(&self) -> String {
85 self.as_slice().debug()
86 }
87}
88
89impl<T: Show> Show for &[T] {
90 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
91 Box::new(fmtools::join("\n", self.iter().map(|item| item._fmt())))
92 }
93
94 fn _fmt_compact(&self) -> Box<dyn fmt::Display + '_> {
95 Box::new(fmtools::join(",", self.iter().map(|item| item._fmt())))
96 }
97
98 fn debug(&self) -> String {
99 let items = self.iter().map(|item| item.debug());
100 fmtools::join("\n", items).to_string()
101 }
102}
103
104impl<T: Show> Show for Option<T> {
105 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
106 self.as_ref().map_or_else(|| ()._fmt(), |item| item._fmt())
107 }
108
109 fn debug(&self) -> String {
110 self.as_ref().map(|item| item.debug()).unwrap_or_default()
111 }
112}
113
114impl Show for () {
115 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
116 Box::new("")
117 }
118
119 fn debug(&self) -> String {
120 String::new()
121 }
122}
123
124impl Show for String {
125 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
126 Box::new(self)
127 }
128}
129
130impl Show for &str {
131 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
132 Box::new(self)
133 }
134}
135
136impl Show for str {
137 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
138 Box::new(self)
139 }
140}
141
142impl Show for bool {
143 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
144 Box::new(self)
145 }
146}
147
148impl Show for i32 {
149 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
150 Box::new(self)
151 }
152}
153
154impl Show for i64 {
155 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
156 Box::new(self)
157 }
158}
159
160impl<K: Show, V: Show> Show for HashMap<K, V> {
161 fn _fmt(&self) -> Box<dyn fmt::Display + '_> {
162 Box::new(fmtools::join(
163 "\n",
164 self.iter()
165 .map(|(key, value)| fmtools::fmt!( {key._fmt():32} "\t" {value._fmt()})),
166 ))
167 }
168}
169
170fn prefixed_items<'a, T>(prefix: &'static str, items: &'a [T]) -> Box<dyn fmt::Display + 'a>
171where
172 T: Show + 'a,
173{
174 Box::new(fmtools::join(
175 "\n",
176 items
177 .iter()
178 .map(move |item| fmtools::fmt!(move {prefix} "\t" { item._fmt() })),
179 ))
180}
181
182fn prefixed_item<'a, T>(prefix: &'static str, item: Option<T>) -> Box<dyn fmt::Display + 'a>
183where
184 T: Show + 'a,
185{
186 item.map_or_else(|| ()._fmt(), |item| prefixed_item0(prefix, item))
187}
188
189fn prefixed_item0<'a, T>(prefix: &'static str, item: T) -> Box<dyn fmt::Display + 'a>
190where
191 T: Show + 'a,
192{
193 Box::new(fmtools::fmt!(move {prefix} "\t" { item._fmt() }))
194}