1use super::*;
2use colored::*;
3use std::collections::HashSet;
4use std::fmt;
5
6#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)]
7pub struct ParamForTableKey {
8 name: String,
9 #[serde(rename = "type")]
10 param_type: String,
11}
12#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
13pub struct ParamForTableValue {
14 eps: HashSet<String>,
15 dms: HashSet<QuePay>,
16 statuses: HashSet<String>,
17 parents: HashSet<String>,
18 children: HashSet<String>,
19 max: Option<i64>,
20 min: Option<i64>,
21 }
23#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
24pub struct ParamForTable {
25 pub name: String,
26 #[serde(rename = "type")]
28 pub param_type: String,
29 pub statuses: Vec<String>,
30 pub dms: Vec<QuePay>,
33 pub eps: Vec<String>,
34 pub parents: Vec<String>,
35 pub children: Vec<String>,
36 pub max: Option<i64>,
37 pub min: Option<i64>,
38 }
40fn vv<T>(vec: &[T], loc: usize) -> String
42where
43 T: Clone + std::fmt::Display,
44{
45 if vec.len() > loc {
46 vec[loc].to_string()
47 } else {
48 String::new()
49 }
50}
51fn color_status(string: &str) -> ColoredString {
52 match string.to_lowercase().chars().next().unwrap_or(' ') {
53 'd' => string.bold().truecolor(107, 114, 128),
54 '2' => string.bold().truecolor(134, 239, 172),
55 '3' => string.bold().truecolor(147, 197, 253),
56 '4' => string.bold().truecolor(253, 224, 71),
57 '5' => string.bold().truecolor(239, 68, 68),
58 _ => string.bold(),
59 }
60}
61fn color_type(string: &str) -> ColoredString {
62 match string.to_lowercase().as_str() {
63 "object" => string.bold().truecolor(248, 113, 113),
64 "array" => string.bold().truecolor(251, 146, 60),
65 "string" => string.bold().truecolor(190, 242, 100),
66 "number" => string.bold().truecolor(125, 211, 252),
67 "integer" => string.bold().truecolor(167, 139, 250),
68 "boolean" => string.bold().truecolor(253, 224, 71),
69 _ => string.bold(),
70 }
71}
72impl fmt::Display for ParamForTable {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 let max = if let Some(m) = self.max {
75 m.to_string()
76 } else {
77 "NULL".to_string()
78 };
79 let min = if let Some(m) = self.min {
80 m.to_string()
81 } else {
82 "NULL".to_string()
83 };
84 let min_max = format!("{}-{}", min, max);
85 let lines = *([
86 self.statuses.len(),
87 self.dms.len(),
88 self.parents.len(),
89 self.children.len(),
90 self.eps.len(),
91 ]
92 .iter()
93 .max()
94 .unwrap_or(&0));
95 let mut string = String::new();
96 let name_len = *([self.name.len(), 25].iter().min().unwrap_or(&0));
97 let parent = vv(&self.parents, 0);
98 let parent = &parent[0..*([parent.len(), 25].iter().min().unwrap_or(&0))];
99 let child = vv(&self.children, 0);
100 let child = &child[0..*([child.len(), 25].iter().min().unwrap_or(&0))];
101 let ep = vv(&self.eps, 0);
102 let ep = &ep[0..*([ep.len(), 75].iter().min().unwrap_or(&0))];
103 string.push_str(&format!(
104 "{:25}|{:7}|{:10}|{:16}|{:75}|{:25}|{:25}|{:15}\n",
105 &self.name.bold()[..name_len],
106 color_type(&self.param_type),
107 color_status(&vv(&self.statuses, 0)),
108 vv(&self.dms, 0).bold(),
109 ep.bold().bright_cyan(),
110 parent.bold(),
111 child.bold(),
112 min_max.bold()
113 ));
114 for i in 1..lines {
115 let parent = vv(&self.parents, i);
116 let parent = &parent[0..*([parent.len(), 25].iter().min().unwrap_or(&0))];
117 let child = vv(&self.children, i);
118 let child = &child[0..*([child.len(), 25].iter().min().unwrap_or(&0))];
119 let ep = vv(&self.eps, i);
120 let ep = &ep[0..*([ep.len(), 75].iter().min().unwrap_or(&0))];
121 string.push_str(&format!(
122 "{:25}|{:7}|{:10}|{:16}|{:75}|{:25}|{:25}|{:15}\n",
123 "",
124 "",
125 color_status(&vv(&self.statuses, i)),
126 vv(&self.dms, i),
127 ep.bold().bright_cyan(),
128 parent.bold(),
129 child.bold(),
130 ""
131 ));
132 }
133 string.push_str(&format!("{:-<210}", ""));
134 write!(f, "{}", string)
135 }
136}
137impl ParamForTable {
138 pub fn from_hash(hash: HashMap<ParamForTableKey, ParamForTableValue>) -> Vec<ParamForTable> {
139 let mut vec = vec![];
140 for (key, value) in hash {
141 vec.push(ParamForTable {
142 name: key.name,
143 param_type: key.param_type,
144 statuses: value.statuses.iter().cloned().collect(),
145 dms: value.dms.iter().cloned().collect(),
146 eps: value.eps.iter().cloned().collect(),
147 parents: value.parents.iter().cloned().collect(),
148 children: value.children.iter().cloned().collect(),
149 max: value.max,
150 min: value.min,
151 });
152 }
153 vec
154 }
155}
156#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
157pub struct ParamTable {
158 info: Info,
159 servers: Vec<String>,
160 pub params: Vec<ParamForTable>,
161 eps: Vec<String>,
162}
163impl ParamTable {
164 pub fn print(&self) {
165 let head = format!(
169 "{:25}|{:7}|{:10}|{:16}|{:75}|{:25}|{:25}|{:15}",
170 "NAME".bold().underline(),
171 "TYPE".bold().underline(),
172 "STATUSES".bold().underline(),
173 "DELIVERY METHODS".bold().underline(),
174 "ENDPOINTS".bold().underline(),
175 "PARENTS".bold().underline(),
176 "CHILDREN".bold().underline(),
177 "MIN-MAX".bold().underline()
178 );
179 for (i, param) in self.params.iter().enumerate() {
181 if i % 50usize == 0 {
182 println!("{}\n{:-<210}", head, "");
183 }
184 println!("{}", param);
185 }
186 }
188 pub fn named_param(&self, param: &str) -> Self {
189 let params = self
190 .params
191 .iter()
192 .filter(|p| p.name.as_str() == param)
193 .cloned()
194 .collect::<Vec<ParamForTable>>();
195 ParamTable {
196 info: self.info.clone(),
197 servers: self.servers.clone(),
198 params,
199 eps: self.eps.clone(),
200 }
201 }
202 pub fn new<T>(value: &Value) -> Self
203 where
204 T: Clone + OAS + for<'de> serde::Deserialize<'de>,
205 {
206 let oas = serde_json::from_value::<T>(value.clone()).unwrap();
207 ParamTable {
208 info: oas.info(),
209 servers: oas
210 .servers()
211 .unwrap_or_default()
212 .iter()
213 .map(|s| s.base_url.clone())
214 .collect(),
215 params: Self::get_params(&oas, value),
216 eps: oas.get_paths().keys().cloned().collect(),
217 }
218 }
219 fn get_all_possible_schemas(schema: &Schema) -> Vec<SchemaRef> {
220 let mut schemas = vec![];
221 if let Some(items) = schema.items.clone() {
222 schemas.push(*items);
223 }
224 if let Some(any) = schema.any_of.clone() {
225 schemas.extend(any);
226 }
227 if let Some(all) = schema.all_of.clone() {
228 schemas.extend(all);
229 }
230 if let Some(one) = schema.one_of.clone() {
231 schemas.extend(one);
232 }
233 schemas
234 }
235 fn get_props(schema: &Schema) -> HashMap<String, SchemaRef> {
236 if let Some(props) = schema.properties.clone() {
237 props
238 } else {
239 HashMap::new()
240 }
241 }
242 fn get_min_max(schema: &Schema, tp: &str) -> (Option<i64>, Option<i64>) {
247 match tp.to_lowercase().as_str() {
248 "string" => {
249 let min = if schema.min_length.is_none() {
250 Some(0)
251 } else {
252 schema.min_length
253 };
254 (min, schema.max_length)
255 }
256
257 "number" | "integer" => {
258 let min = if let Some(m) = schema.minimum {
259 Some(m as i64)
260 } else {
261 Some(i64::MIN)
262 };
263 let max = if let Some(m) = schema.maximum {
264 Some(m as i64)
265 } else {
266 Some(i64::MAX)
267 };
268 (min, max)
269 }
270 "array" => {
271 let min = if schema.min_items.is_none() {
272 Some(0)
273 } else {
274 schema.min_items
275 };
276 (min, schema.max_items)
277 }
278 "object" => {
279 let min = if schema.min_properties.is_none() {
280 Some(0)
281 } else {
282 schema.min_properties
283 };
284 (min, schema.max_properties)
285 }
286 _ => (Some(0), Some(0)),
287 }
288 }
289 fn get_name_s_ref(s_ref: &SchemaRef, value: &Value, name: &Option<String>) -> String {
290 let schema = s_ref.inner(value);
291 if let Some(ref t) = schema.title {
292 t.to_string()
293 } else if let SchemaRef::Ref(r) = s_ref {
294 r.param_ref.split('/').last().unwrap().to_string()
295 } else if let Some(n) = name {
296 n.to_string()
297 } else {
298 String::new()
299 }
300 }
301 #[allow(clippy::too_many_arguments)]
302 fn get_params_rec(
303 params: &mut HashMap<ParamForTableKey, ParamForTableValue>,
304 schema_ref: SchemaRef,
305 path: String,
306 parent: Option<String>,
307 dm: QuePay,
308 status: Option<String>,
309 name_f: Option<String>,
310 value: &Value,
311 ) {
312 let mut children = vec![];
313 let schema = schema_ref.inner(value);
314 let name = Self::get_name_s_ref(&schema_ref, value, &name_f);
315 for s in Self::get_all_possible_schemas(&schema) {
316 let n = Self::get_name_s_ref(&schema_ref, value, &name_f);
317 children.push(n.clone());
318 Self::get_params_rec(
319 params,
320 s,
321 path.clone(),
322 Some(name.clone()),
323 dm,
324 status.clone(),
325 Some(n),
326 value,
327 );
328 }
329 for (n, prop) in Self::get_props(&schema) {
330 children.push(n.clone());
331 Self::get_params_rec(
332 params,
333 prop,
334 path.clone(),
335 Some(name.clone()),
336 dm,
337 status.clone(),
338 Some(n),
339 value,
340 );
341 }
342 let tp = if let Some(ref tp) = schema.schema_type {
343 tp.to_string()
344 } else {
345 String::from("object")
346 };
347 let key = ParamForTableKey {
348 name,
349 param_type: tp.clone(),
350 };
351 let val = params
352 .entry(key)
353 .or_insert_with(ParamForTableValue::default);
354 val.eps.insert(path);
355 val.dms.insert(dm);
356 if let Some(st) = status {
357 val.statuses.insert(st);
358 }
359 if let Some(p) = parent {
360 val.parents.insert(p);
361 }
362 val.children.extend(children);
363 let (min, max) = Self::get_min_max(&schema, &tp);
364 if let Some(m) = min {
365 if m > val.min.unwrap_or(i64::MIN) {
366 val.min = min;
367 }
368 }
369 if let Some(m) = max {
370 if m < val.max.unwrap_or(i64::MAX) {
371 val.max = max;
372 }
373 }
374 }
375 pub fn get_params<T>(oas: &T, value: &Value) -> Vec<ParamForTable>
376 where
377 T: OAS,
378 {
379 let mut params: HashMap<ParamForTableKey, ParamForTableValue> = HashMap::new();
380 for (path, item) in oas.get_paths() {
381 for (_, op) in item.get_ops() {
382 if let Some(b) = &op.request_body {
383 for (_, m_t) in b.inner(value).content {
384 if let Some(schema) = m_t.schema {
385 Self::get_params_rec(
386 &mut params,
387 schema,
388 path.clone(),
389 None,
390 QuePay::Payload,
391 None,
392 None,
393 value,
394 );
395 }
396 }
397 }
398 for (status, payload) in op.responses() {
399 if let Some(c) = payload.inner(value).content {
400 for (_, m_t) in c {
401 if let Some(schema) = m_t.schema {
402 Self::get_params_rec(
403 &mut params,
404 schema,
405 path.clone(),
406 None,
407 QuePay::Response,
408 Some(status.clone()),
409 None,
410 value,
411 );
412 }
413 }
414 }
415 }
416 let params1 = if let Some(p) = &op.parameters {
417 p.to_vec()
418 } else {
419 vec![]
420 };
421 for param in params1 {
422 let param = param.inner(value);
423 if let Some(schema) = param.schema.clone() {
424 Self::get_params_rec(
425 &mut params,
426 schema,
427 path.clone(),
428 None,
429 param.from(),
430 None,
431 Some(param.name),
432 value,
433 );
434 }
435 }
436 }
437 let params1 = if let Some(p) = item.parameters {
438 p
439 } else {
440 vec![]
441 };
442 for param in params1 {
443 let param = param.inner(value);
444 if let Some(schema) = param.schema.clone() {
445 Self::get_params_rec(
446 &mut params,
447 schema,
448 path.clone(),
449 None,
450 param.from(),
451 None,
452 Some(param.name),
453 value,
454 );
455 }
456 }
457 }
458 ParamForTable::from_hash(params)
459 }
460}