swagger/tables/
param_table.rs

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    //default:Option<SchemaStrInt>,
22}
23#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
24pub struct ParamForTable {
25    pub name: String,
26    //probably will become an Enum
27    #[serde(rename = "type")]
28    pub param_type: String,
29    pub statuses: Vec<String>,
30    //probably will become an Enum
31    //from:String,
32    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    //default:Option<SchemaStrInt>,
39}
40//value_from_vec
41fn 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        //println!("info:{:?}",self.info);
166        //println!("urls:{:?}",self.servers);
167        //println!("eps:{:?}",self.eps);
168        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        //println!("{}\n{:-<270}",head,"");
180        for (i, param) in self.params.iter().enumerate() {
181            if i % 50usize == 0 {
182                println!("{}\n{:-<210}", head, "");
183            }
184            println!("{}", param);
185        }
186        //println!("{}",head);
187    }
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    /*
243    fn get_min_max_float(schema:&Schema)->(Option<f64>,Option<f64>){
244        (schema.minimum,schema.maximum)
245    }*/
246    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}