dbuggery 0.0.1

Simple rust debugging crate
Documentation
use std::{
    fs,
    io::Write,
    env, 
    fmt::Display,
};              

type DynRes<T> = Result<T, Box<dyn std::error::Error>>;

const XDG_ERR: &str = 
    "Error: debug_append, xdg_dir";
const EXISTS_ERR: &str = 
    "Error: debug_append, failed dir exists";
const DIR_CREATION_ERR: &str = 
    "Error: debug_append, failed dir creation";
const FOPEN_ERR: &str = 
    "Error: debug_append, failed file open"; 
const WRITE_ALL_ERR: &str = 
    "Error: debug_append, file write_all";

#[macro_export]
macro_rules! err {
    ($err:expr) => {
        match $err {
            Err(e) => return Err(Box::new(e)),
            Ok(thing) => thing,
        }
    };
}

fn get_xdg_state_dir(
    dir_name: impl Display,
) -> DynRes<String> {
    const XDG_VAR: &str = "XDG_STATE_HOME";     
    const ALT_VAR: &str = "HOME";
    const ALT_POSTFIX: &str = /*$HOME*/".local/state";

    let dir = if let Ok(dir) = env::var(XDG_VAR) {
        dir
    } else {
        format!(
            "{}/{ALT_POSTFIX}/{}",
            env::var(ALT_VAR)?,
            dir_name,
        )
    };

    if !fs::exists(&dir)? {
        fs::create_dir_all(&dir)?;
    }

    return Ok(dir);
}

/// only compiles in debug mode
#[cfg(debug_assertions)]
pub fn debug_append(
    buf: impl AsRef<[u8]>, 
    fname: impl AsRef<str>,
    dir_name: impl AsRef<str>,
) {

    let dir = get_xdg_state_dir(dir_name.as_ref())
        .expect(XDG_ERR);

    if !fs::exists(&dir).expect(EXISTS_ERR) {
        fs::create_dir_all(&dir).expect(DIR_CREATION_ERR);
    }

    let path = format!("{dir}/{}.log", fname.as_ref());
    let mut file = fs::OpenOptions::new()
        .read(true)
        .append(true)
        .create(true)
        .open(path)
        .expect(FOPEN_ERR);

    let _ = &mut file.write_all(buf.as_ref())
        .expect(WRITE_ALL_ERR);
}

/// compiles in debug and release mode
pub fn append(
    buf: impl AsRef<[u8]>, 
    fname: impl AsRef<str>,
    dir_name: impl AsRef<str>,
) {
    let dir = get_xdg_state_dir(dir_name.as_ref())
        .expect(XDG_ERR);

    if !fs::exists(&dir).expect(EXISTS_ERR) {
        fs::create_dir_all(&dir).expect(DIR_CREATION_ERR);
    }

    let path = format!("{dir}/{}.log", fname.as_ref());
    let mut file = fs::OpenOptions::new()
        .read(true)
        .append(true)
        .create(true)
        .open(path)
        .expect(FOPEN_ERR);

    let _ = &mut file.write_all(buf.as_ref())
        .expect(WRITE_ALL_ERR);
}

/// only compiles in debug mode
#[cfg(debug_assertions)]
pub fn debug_err_append<'a, T, E: Display>(
    error: &Result<T, E>,
    fname: &str,
    dir_name: &str,
) {
    if let Err(err) = error {
        let dir = get_xdg_state_dir(dir_name).expect(XDG_ERR);

        let path = format!("{}/{}", dir, fname);
        if !fs::exists(&path).expect(EXISTS_ERR)
        {
            fs::create_dir_all(&dir).expect(DIR_CREATION_ERR);
        }

        let mut file = fs::OpenOptions::new()
            .read(true)
            .append(true)
            .create(true)
            .open(path)
            .expect(FOPEN_ERR);

        let err_msg = err.to_string();
        let _ = &mut file.write_all(
            err_msg.as_ref()).expect(WRITE_ALL_ERR);
    }
}  

/// compiles in release and debug mode
pub fn err_append<'a, T, E: Display>(
    error: &Result<T, E>,
    fname: &str,
    dir_name: &str,
) {
    if let Err(err) = error {
        let dir = get_xdg_state_dir(dir_name).expect(XDG_ERR);

        let path = format!("{}/{}", dir, fname);
        if !fs::exists(&path).expect(EXISTS_ERR)
        {
            fs::create_dir_all(&dir).expect(DIR_CREATION_ERR);
        }

        let mut file = fs::OpenOptions::new()
            .read(true)
            .append(true)
            .create(true)
            .open(path)
            .expect(FOPEN_ERR);

        let err_msg = err.to_string();
        let _ = &mut file.write_all(
            err_msg.as_ref()).expect(WRITE_ALL_ERR);
    }
}