printjsonerr/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use yansi::Paint;
4
5pub fn printjsonerr(ajson: &serde_json::Value, ln: bool) {
6    let result = jsonerrtoprettystring(ajson);
7    if ln == true {
8        println!("{}", result);
9    } else {
10        print!("{}", result);
11    }
12}
13
14#[macro_export]
15macro_rules! printjsonerr {
16    // without pointer, add return carriage
17    ($x:expr) => {
18        printjsonerr(&$x, true)
19    };
20    // with pointer, add return carriage
21    (&$x:expr) => {
22        printjsonerr($x, true)
23    };
24}
25
26pub fn jsonerrtoprettystring(data: &serde_json::Value) -> String {
27    let mut tmparray: Vec<String> = vec![];
28    traversejson(&data, "", &mut tmparray);
29    let result = tmparray.join("\n");
30    return result;
31}
32
33static PREPENDSEP: &str = "|";
34static PREPENDSPACES: &str = "        ";
35static ORIGINTXT: &str = "origin:";
36// static ORIGINTXT: &str = "origin ▶";
37
38// https://en.wikipedia.org/wiki/Box_Drawing
39static BLOCSTART: &str = "┌----------------------------";
40static _BLOCEND: &str = "└----------------------------";
41
42fn traversejson(avalue: &serde_json::Value, prepend: &str, atmparray: &mut Vec<String>) {
43    // is a jsonerr with .meta, .err, iserr, .isout ?
44    let resultisjsonerr = fn_isjsonerr(avalue);
45    // dbg!(&resultisjsonerr);
46
47    if resultisjsonerr.isjsonerr == false {
48        atmparray.push(serde_json::to_string_pretty(avalue).unwrap());
49    } else {
50        atmparray.push(format!("{prepend}{BLOCSTART}",));
51        if resultisjsonerr.with_key_meta == true {
52            let mut metas: Vec<String> = vec![];
53            if resultisjsonerr.with_key_meta_whoami_filename == true {
54                metas.push(resultisjsonerr.whoami_filename.unwrap());
55                if resultisjsonerr.with_key_meta_whoami_line == true {
56                    metas.push(", line=".into());
57                    metas.push(resultisjsonerr.whoami_line.unwrap().to_string());
58                }
59                if resultisjsonerr.with_key_meta_whoami_function == true {
60                    metas.push(", function=".into());
61                    metas.push(resultisjsonerr.whoami_function.unwrap().to_string());
62                    metas.push("()".into());
63                }
64            }
65            let meta = metas.join("");
66            atmparray.push(format!(
67                "{prepend}{PREPENDSEP} meta: {meta}",
68                meta = Paint::white(meta).italic()
69            ));
70        }
71        if resultisjsonerr.with_key_err == true {
72            let code = resultisjsonerr.code.unwrap();
73            let message = resultisjsonerr.message.unwrap();
74            atmparray.push(format!(
75                "{prepend}{PREPENDSEP} {code}: {message}",
76                code = Paint::white(code).underline(),
77                message = Paint::white(message).bold()
78            ));
79        }
80        if resultisjsonerr.with_key_err_origin == true {
81            if resultisjsonerr.with_key_err_origin_isjsonerr == true {
82                atmparray.push(format!(
83                    // "{prepend}{PREPENDSEP} origin ▶ ",
84                    "{prepend}{PREPENDSEP} {origin}",
85                    origin = Paint::white(ORIGINTXT).italic(),
86                ));
87
88                let newprepend = newprepend(prepend);
89                let newprepend = newprepend.as_str();
90
91                traversejson(&resultisjsonerr.origin.unwrap(), newprepend, atmparray);
92            } else {
93                atmparray.push(format!(
94                    "{prepend}{PREPENDSEP} {origin}",
95                    origin = Paint::white(ORIGINTXT).italic(),
96                ));
97
98                let newprepend = newprepend(prepend);
99                let newprepend = newprepend.as_str();
100
101                atmparray.push(format!("{newprepend}{BLOCSTART}",));
102
103                let code = "std:error:Error";
104                let origin = resultisjsonerr.origin.unwrap();
105                let mut message = serde_json::to_string(&origin).unwrap();
106                if origin.is_string() {
107                    message = origin.as_str().unwrap().to_string();
108                }
109
110                atmparray.push(format!(
111                    "{newprepend}{PREPENDSEP} {code}: {message}",
112                    code = Paint::white(code).underline(),
113                    message = Paint::white(message).bold()
114                ));
115
116                // atmparray.push(format!("{newprepend}{BLOCEND}",));
117            }
118        }
119        // atmparray.push(format!("{prepend}{BLOCEND}",));
120    }
121}
122
123fn newprepend(previousprepend: &str) -> String {
124    let newprepend = [previousprepend.clone(), { PREPENDSEP }, PREPENDSPACES].join("");
125    newprepend
126}
127
128#[allow(dead_code)]
129#[derive(Debug)]
130struct StructIsJsonErr {
131    pub isjsonerr: bool,
132    pub with_key_meta: bool,
133    pub with_value_meta_object: bool,
134    pub with_key_meta_whoami: bool,
135    pub with_key_meta_whoami_filename: bool,
136    pub with_key_meta_whoami_function: bool,
137    pub with_key_meta_whoami_line: bool,
138    pub with_key_iserr: bool,
139    pub with_value_iserr_boolean_true: bool,
140    pub with_key_isout: bool,
141    pub with_value_isout_boolean_true: bool,
142    pub with_key_err: bool,
143    pub with_value_err_object: bool,
144    pub with_value_err_code_string: bool,
145    pub code: Option<String>,
146    pub with_value_err_message_string: bool,
147    pub message: Option<String>,
148    pub with_key_err_origin: bool,
149    pub with_key_err_origin_isjsonerr: bool,
150    pub origin: Option<serde_json::Value>,
151    pub whoami_filename: Option<String>,
152    pub whoami_function: Option<String>,
153    pub whoami_line: Option<i64>,
154}
155
156/// value is an object with
157/// - .meta,
158/// - .iserr,
159/// - .isout,
160/// - .err,
161/// - .err.code,
162/// - .err.message,
163/// - .err.payload,
164/// - .err.origin
165fn fn_isjsonerr(avalue: &serde_json::Value) -> StructIsJsonErr {
166    let mut isjsonerr = false;
167    let mut with_key_meta = false;
168    let mut with_value_meta_object = false;
169    let mut with_key_meta_whoami = false;
170    let mut with_key_meta_whoami_filename = false;
171    let mut with_key_meta_whoami_function = false;
172    let mut with_key_meta_whoami_line = false;
173    let mut with_key_iserr = false;
174    let mut with_value_iserr_boolean_true = false;
175    let mut with_key_isout = false;
176    let mut with_value_isout_boolean_true = false;
177    let mut with_key_err = false;
178    let mut with_value_err_object = false;
179    let mut with_value_err_code_string = false;
180    let mut code: Option<String> = None;
181    let mut with_value_err_message_string = false;
182    let mut message: Option<String> = None;
183    let mut with_key_err_origin = false;
184    let mut with_key_err_origin_isjsonerr = false;
185    let mut origin: Option<serde_json::Value> = None;
186    let mut whoami_filename: Option<String> = None;
187    let mut whoami_function: Option<String> = None;
188    let mut whoami_line: Option<i64> = None;
189
190    if avalue.is_object() == true {
191        let tmpvalue = avalue.as_object().unwrap();
192        for keyvalue in tmpvalue {
193            let (key, value) = keyvalue;
194            if key == "meta" {
195                with_key_meta = true;
196                if value.is_object() == true {
197                    with_value_meta_object = true;
198                    let tmpvalue = value.as_object().unwrap();
199                    for keyvalue in tmpvalue {
200                        let (key, value) = keyvalue;
201                        if key == "whoami" {
202                            if value.is_object() == true {
203                                with_key_meta_whoami = true;
204                                let tmpvalue = value.as_object().unwrap();
205                                for keyvalue in tmpvalue {
206                                    let (key, value) = keyvalue;
207                                    if key == "filename" {
208                                        if value.is_string() == true {
209                                            with_key_meta_whoami_filename = true;
210                                            let value = value.as_str().unwrap();
211                                            whoami_filename = Some(value.into());
212                                        }
213                                    }
214                                    if key == "function" {
215                                        if value.is_string() == true {
216                                            with_key_meta_whoami_function = true;
217                                            let value = value.as_str().unwrap();
218                                            whoami_function = Some(value.into());
219                                        }
220                                    }
221                                    if key == "line" {
222                                        if value.is_i64() == true {
223                                            with_key_meta_whoami_line = true;
224                                            let value = value.as_i64().unwrap();
225                                            whoami_line = Some(value.into());
226                                        }
227                                    }
228                                }
229                            }
230                        }
231                    }
232                }
233            }
234            if key == "iserr" {
235                with_key_iserr = true;
236                if value.is_boolean() == true {
237                    let value = value.as_bool().unwrap();
238                    if value == true {
239                        with_value_iserr_boolean_true = true;
240                    }
241                }
242            }
243            if key == "isout" {
244                with_key_isout = true;
245                if value.is_boolean() == true {
246                    let value = value.as_bool().unwrap();
247                    if value == true {
248                        with_value_isout_boolean_true = true;
249                    }
250                }
251            }
252            if key == "err" {
253                with_key_err = true;
254                if value.is_object() == true {
255                    with_value_err_object = true;
256                    let tmpvalue = value.as_object().unwrap();
257                    for keyvalue in tmpvalue {
258                        let (key, value) = keyvalue;
259                        if key == "code" {
260                            if value.is_string() == true {
261                                with_value_err_code_string = true;
262                                let value = value.as_str().unwrap();
263                                code = Some(value.into());
264                            }
265                        }
266                        if key == "message" {
267                            if value.is_string() == true {
268                                with_value_err_message_string = true;
269                                let value = value.as_str().unwrap();
270                                message = Some(value.into());
271                            }
272                        }
273                        if key == "origin" {
274                            with_key_err_origin = true;
275                            let result = fn_isjsonerr(&value);
276                            with_key_err_origin_isjsonerr = result.isjsonerr;
277                            origin = Some(value.clone());
278                        }
279                    }
280                }
281            }
282        }
283    } else {
284        // 'avalue' is not an object
285        // isjsonerr stay at false
286    }
287
288    // so,is a jsonerr ?
289    if with_key_err == true
290        && with_value_err_object == true
291        && with_value_err_code_string
292        && with_value_err_message_string
293    {
294        isjsonerr = true;
295    }
296
297    // return
298    // return isjsonerr;
299    StructIsJsonErr {
300        isjsonerr,
301        with_key_meta,
302        with_value_meta_object,
303        with_key_meta_whoami,
304        with_key_meta_whoami_filename,
305        with_key_meta_whoami_function,
306        with_key_meta_whoami_line,
307        with_key_iserr,
308        with_value_iserr_boolean_true,
309        with_key_isout,
310        with_value_isout_boolean_true,
311        with_key_err,
312        with_value_err_object,
313        with_value_err_code_string,
314        code,
315        with_value_err_message_string,
316        message,
317        with_key_err_origin,
318        with_key_err_origin_isjsonerr,
319        origin,
320        whoami_filename,
321        whoami_function,
322        whoami_line,
323    }
324}