hhh 1.0.1

The hhh Binary File Processor
Documentation
// hhh
// Copyright (c) 2023 by Stacy Prowell.  All rights reserved.
// https://gitlab.com/sprowell/hhh

//! Define the library content.
//!
//! Important structs are [`Generator`](generator::Generator) and [`Reader`](reader::Reader).  See also the
//! convenience methods [`write_hexdump`] and [`read_hexdump`].

// Warnings FAIL the build when the "strict" feature is set.
#![cfg_attr(feature = "strict", deny(warnings))]
// Set the logo for the generated documentation.
#![doc(html_logo_url = "https://gitlab.com/sprowell/hhh/-/raw/master/etc/logo.png")]
// Enable lots of lints!
#![deny(missing_docs,
        //missing_debug_implementations,
        missing_copy_implementations,
        trivial_casts,
        trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces,
        unused_qualifications)]

/// Retrieve and save the version number from the Cargo manifest.
/// This is populated during compilation.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// Retrieve and save the short hash number from the Cargo manifest.
/// This is populated during compilation.
pub const HASH: &str = env!("SHORT_HASH");

pub mod generator;
pub mod options;
use std::{
    fs::{DirBuilder, OpenOptions},
    path::PathBuf,
};

use directories_next::ProjectDirs;
pub use generator::write_hexdump;
pub mod byte_data;
pub mod directive_def;
pub mod directives;
pub mod expression;
pub mod reader;
pub use reader::read_hexdump;
pub mod math;
pub mod read_configuration;

#[cfg(test)]
mod test;

/// Obtain the configuration folder for hhh.
///
/// Return the platform-specific appropriate configuration folder, or
/// the overridden configuration folder, or -- as a last resort -- the
/// current directory.  This will create the directory if it does
/// not exist, and returns an error only if the directory cannot be
/// created.
pub fn get_config_directory() -> std::io::Result<PathBuf> {
    // Get the configuration directory, using the current directory if we cannot
    // get an actual configuration directory.
    let mut config = PathBuf::new();
    if let Some(proj_dirs) = ProjectDirs::from("", "binary-tools", "hhh") {
        config.push(proj_dirs.config_dir());
    } else {
        config.push(".");
    }

    // Make sure the directory exists, and create it if it does not.
    DirBuilder::new().recursive(true).create(&config)?;
    Ok(config)
}

/// Return the central configuration file.
///
/// If this file does not exist, it is created empty.
pub fn get_config_file() -> std::io::Result<PathBuf> {
    let mut path = get_config_directory()?;
    path.push("hhh.config");
    OpenOptions::new()
        .write(true)
        .create(true)
        .open(path.clone())?;
    Ok(path)
}

/// Configure logging.
///
/// This method should be called before any other logging method or
/// macros are invoked to initialize the logging system.
///
/// This method uses the `env_logger` crate to initialize the logging
/// system from the environment variables `HHH_LOG` and
/// `HHH_LOG_STYLE`.
pub fn configure_logging() {
    // Configure logging based on environment variables.
    let mut builder = env_logger::Builder::new();
    builder.filter_level(log::LevelFilter::Warn);
    let env = env_logger::Env::new()
        .filter("HHH_LOG")
        .write_style("HHH_LOG_STYLE");
    builder.parse_env(env);
    builder.init();
}

#[cfg(test)]
mod lib_test {
    use crate::{configure_logging, get_config_file};

    #[test]
    fn get_config_file_test() {
        let file = get_config_file();
        assert!(file.is_ok());
    }

    #[test]
    fn configure_logging_test() {
        configure_logging();
    }
}