printjsonerr 0.0.1

print json err
Documentation
#![doc = include_str!("../README.md")]

use yansi::Paint;

pub fn printjsonerr(ajson: &serde_json::Value, ln: bool) {
    let result = jsonerrtoprettystring(ajson);
    if ln == true {
        println!("{}", result);
    } else {
        print!("{}", result);
    }
}

#[macro_export]
macro_rules! printjsonerr {
    // without pointer, add return carriage
    ($x:expr) => {
        printjsonerr(&$x, true)
    };
    // with pointer, add return carriage
    (&$x:expr) => {
        printjsonerr($x, true)
    };
}

pub fn jsonerrtoprettystring(data: &serde_json::Value) -> String {
    let mut tmparray: Vec<String> = vec![];
    traversejson(&data, "", &mut tmparray);
    let result = tmparray.join("\n");
    return result;
}

static PREPENDSEP: &str = "|";
static PREPENDSPACES: &str = "        ";
static ORIGINTXT: &str = "origin:";
// static ORIGINTXT: &str = "origin ▶";

// https://en.wikipedia.org/wiki/Box_Drawing
static BLOCSTART: &str = "┌----------------------------";
static _BLOCEND: &str = "└----------------------------";

fn traversejson(avalue: &serde_json::Value, prepend: &str, atmparray: &mut Vec<String>) {
    // is a jsonerr with .meta, .err, iserr, .isout ?
    let resultisjsonerr = fn_isjsonerr(avalue);
    // dbg!(&resultisjsonerr);

    if resultisjsonerr.isjsonerr == false {
        atmparray.push(serde_json::to_string_pretty(avalue).unwrap());
    } else {
        atmparray.push(format!("{prepend}{BLOCSTART}",));
        if resultisjsonerr.with_key_meta == true {
            let mut metas: Vec<String> = vec![];
            if resultisjsonerr.with_key_meta_whoami_filename == true {
                metas.push(resultisjsonerr.whoami_filename.unwrap());
                if resultisjsonerr.with_key_meta_whoami_line == true {
                    metas.push(", line=".into());
                    metas.push(resultisjsonerr.whoami_line.unwrap().to_string());
                }
                if resultisjsonerr.with_key_meta_whoami_function == true {
                    metas.push(", function=".into());
                    metas.push(resultisjsonerr.whoami_function.unwrap().to_string());
                    metas.push("()".into());
                }
            }
            let meta = metas.join("");
            atmparray.push(format!(
                "{prepend}{PREPENDSEP} meta: {meta}",
                meta = Paint::white(meta).italic()
            ));
        }
        if resultisjsonerr.with_key_err == true {
            let code = resultisjsonerr.code.unwrap();
            let message = resultisjsonerr.message.unwrap();
            atmparray.push(format!(
                "{prepend}{PREPENDSEP} {code}: {message}",
                code = Paint::white(code).underline(),
                message = Paint::white(message).bold()
            ));
        }
        if resultisjsonerr.with_key_err_origin == true {
            if resultisjsonerr.with_key_err_origin_isjsonerr == true {
                atmparray.push(format!(
                    // "{prepend}{PREPENDSEP} origin ▶ ",
                    "{prepend}{PREPENDSEP} {origin}",
                    origin = Paint::white(ORIGINTXT).italic(),
                ));

                let newprepend = newprepend(prepend);
                let newprepend = newprepend.as_str();

                traversejson(&resultisjsonerr.origin.unwrap(), newprepend, atmparray);
            } else {
                atmparray.push(format!(
                    "{prepend}{PREPENDSEP} {origin}",
                    origin = Paint::white(ORIGINTXT).italic(),
                ));

                let newprepend = newprepend(prepend);
                let newprepend = newprepend.as_str();

                atmparray.push(format!("{newprepend}{BLOCSTART}",));

                let code = "std:error:Error";
                let origin = resultisjsonerr.origin.unwrap();
                let mut message = serde_json::to_string(&origin).unwrap();
                if origin.is_string() {
                    message = origin.as_str().unwrap().to_string();
                }

                atmparray.push(format!(
                    "{newprepend}{PREPENDSEP} {code}: {message}",
                    code = Paint::white(code).underline(),
                    message = Paint::white(message).bold()
                ));

                // atmparray.push(format!("{newprepend}{BLOCEND}",));
            }
        }
        // atmparray.push(format!("{prepend}{BLOCEND}",));
    }
}

fn newprepend(previousprepend: &str) -> String {
    let newprepend = [previousprepend.clone(), { PREPENDSEP }, PREPENDSPACES].join("");
    newprepend
}

#[allow(dead_code)]
#[derive(Debug)]
struct StructIsJsonErr {
    pub isjsonerr: bool,
    pub with_key_meta: bool,
    pub with_value_meta_object: bool,
    pub with_key_meta_whoami: bool,
    pub with_key_meta_whoami_filename: bool,
    pub with_key_meta_whoami_function: bool,
    pub with_key_meta_whoami_line: bool,
    pub with_key_iserr: bool,
    pub with_value_iserr_boolean_true: bool,
    pub with_key_isout: bool,
    pub with_value_isout_boolean_true: bool,
    pub with_key_err: bool,
    pub with_value_err_object: bool,
    pub with_value_err_code_string: bool,
    pub code: Option<String>,
    pub with_value_err_message_string: bool,
    pub message: Option<String>,
    pub with_key_err_origin: bool,
    pub with_key_err_origin_isjsonerr: bool,
    pub origin: Option<serde_json::Value>,
    pub whoami_filename: Option<String>,
    pub whoami_function: Option<String>,
    pub whoami_line: Option<i64>,
}

/// value is an object with
/// - .meta,
/// - .iserr,
/// - .isout,
/// - .err,
/// - .err.code,
/// - .err.message,
/// - .err.payload,
/// - .err.origin
fn fn_isjsonerr(avalue: &serde_json::Value) -> StructIsJsonErr {
    let mut isjsonerr = false;
    let mut with_key_meta = false;
    let mut with_value_meta_object = false;
    let mut with_key_meta_whoami = false;
    let mut with_key_meta_whoami_filename = false;
    let mut with_key_meta_whoami_function = false;
    let mut with_key_meta_whoami_line = false;
    let mut with_key_iserr = false;
    let mut with_value_iserr_boolean_true = false;
    let mut with_key_isout = false;
    let mut with_value_isout_boolean_true = false;
    let mut with_key_err = false;
    let mut with_value_err_object = false;
    let mut with_value_err_code_string = false;
    let mut code: Option<String> = None;
    let mut with_value_err_message_string = false;
    let mut message: Option<String> = None;
    let mut with_key_err_origin = false;
    let mut with_key_err_origin_isjsonerr = false;
    let mut origin: Option<serde_json::Value> = None;
    let mut whoami_filename: Option<String> = None;
    let mut whoami_function: Option<String> = None;
    let mut whoami_line: Option<i64> = None;

    if avalue.is_object() == true {
        let tmpvalue = avalue.as_object().unwrap();
        for keyvalue in tmpvalue {
            let (key, value) = keyvalue;
            if key == "meta" {
                with_key_meta = true;
                if value.is_object() == true {
                    with_value_meta_object = true;
                    let tmpvalue = value.as_object().unwrap();
                    for keyvalue in tmpvalue {
                        let (key, value) = keyvalue;
                        if key == "whoami" {
                            if value.is_object() == true {
                                with_key_meta_whoami = true;
                                let tmpvalue = value.as_object().unwrap();
                                for keyvalue in tmpvalue {
                                    let (key, value) = keyvalue;
                                    if key == "filename" {
                                        if value.is_string() == true {
                                            with_key_meta_whoami_filename = true;
                                            let value = value.as_str().unwrap();
                                            whoami_filename = Some(value.into());
                                        }
                                    }
                                    if key == "function" {
                                        if value.is_string() == true {
                                            with_key_meta_whoami_function = true;
                                            let value = value.as_str().unwrap();
                                            whoami_function = Some(value.into());
                                        }
                                    }
                                    if key == "line" {
                                        if value.is_i64() == true {
                                            with_key_meta_whoami_line = true;
                                            let value = value.as_i64().unwrap();
                                            whoami_line = Some(value.into());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if key == "iserr" {
                with_key_iserr = true;
                if value.is_boolean() == true {
                    let value = value.as_bool().unwrap();
                    if value == true {
                        with_value_iserr_boolean_true = true;
                    }
                }
            }
            if key == "isout" {
                with_key_isout = true;
                if value.is_boolean() == true {
                    let value = value.as_bool().unwrap();
                    if value == true {
                        with_value_isout_boolean_true = true;
                    }
                }
            }
            if key == "err" {
                with_key_err = true;
                if value.is_object() == true {
                    with_value_err_object = true;
                    let tmpvalue = value.as_object().unwrap();
                    for keyvalue in tmpvalue {
                        let (key, value) = keyvalue;
                        if key == "code" {
                            if value.is_string() == true {
                                with_value_err_code_string = true;
                                let value = value.as_str().unwrap();
                                code = Some(value.into());
                            }
                        }
                        if key == "message" {
                            if value.is_string() == true {
                                with_value_err_message_string = true;
                                let value = value.as_str().unwrap();
                                message = Some(value.into());
                            }
                        }
                        if key == "origin" {
                            with_key_err_origin = true;
                            let result = fn_isjsonerr(&value);
                            with_key_err_origin_isjsonerr = result.isjsonerr;
                            origin = Some(value.clone());
                        }
                    }
                }
            }
        }
    } else {
        // 'avalue' is not an object
        // isjsonerr stay at false
    }

    // so,is a jsonerr ?
    if with_key_err == true
        && with_value_err_object == true
        && with_value_err_code_string
        && with_value_err_message_string
    {
        isjsonerr = true;
    }

    // return
    // return isjsonerr;
    StructIsJsonErr {
        isjsonerr,
        with_key_meta,
        with_value_meta_object,
        with_key_meta_whoami,
        with_key_meta_whoami_filename,
        with_key_meta_whoami_function,
        with_key_meta_whoami_line,
        with_key_iserr,
        with_value_iserr_boolean_true,
        with_key_isout,
        with_value_isout_boolean_true,
        with_key_err,
        with_value_err_object,
        with_value_err_code_string,
        code,
        with_value_err_message_string,
        message,
        with_key_err_origin,
        with_key_err_origin_isjsonerr,
        origin,
        whoami_filename,
        whoami_function,
        whoami_line,
    }
}