hhh/
lib.rs

1// hhh
2// Copyright (c) 2023 by Stacy Prowell.  All rights reserved.
3// https://gitlab.com/sprowell/hhh
4
5//! Define the library content.
6//!
7//! Important structs are [`Generator`](generator::Generator) and [`Reader`](reader::Reader).  See also the
8//! convenience methods [`write_hexdump`] and [`read_hexdump`].
9
10// Warnings FAIL the build when the "strict" feature is set.
11#![cfg_attr(feature = "strict", deny(warnings))]
12// Set the logo for the generated documentation.
13#![doc(html_logo_url = "https://gitlab.com/sprowell/hhh/-/raw/master/etc/logo.png")]
14// Enable lots of lints!
15#![deny(missing_docs,
16        //missing_debug_implementations,
17        missing_copy_implementations,
18        trivial_casts,
19        trivial_numeric_casts,
20        unsafe_code,
21        unstable_features,
22        unused_import_braces,
23        unused_qualifications)]
24
25/// Retrieve and save the version number from the Cargo manifest.
26/// This is populated during compilation.
27pub const VERSION: &str = env!("CARGO_PKG_VERSION");
28
29/// Retrieve and save the short hash number from the Cargo manifest.
30/// This is populated during compilation.
31pub const HASH: &str = env!("SHORT_HASH");
32
33pub mod generator;
34pub mod options;
35use std::{
36    fs::{DirBuilder, OpenOptions},
37    path::PathBuf,
38};
39
40use directories_next::ProjectDirs;
41pub use generator::write_hexdump;
42pub mod byte_data;
43pub mod directive_def;
44pub mod directives;
45pub mod expression;
46pub mod reader;
47pub use reader::read_hexdump;
48pub mod math;
49pub mod read_configuration;
50
51#[cfg(test)]
52mod test;
53
54/// Obtain the configuration folder for hhh.
55///
56/// Return the platform-specific appropriate configuration folder, or
57/// the overridden configuration folder, or -- as a last resort -- the
58/// current directory.  This will create the directory if it does
59/// not exist, and returns an error only if the directory cannot be
60/// created.
61pub fn get_config_directory() -> std::io::Result<PathBuf> {
62    // Get the configuration directory, using the current directory if we cannot
63    // get an actual configuration directory.
64    let mut config = PathBuf::new();
65    if let Some(proj_dirs) = ProjectDirs::from("", "binary-tools", "hhh") {
66        config.push(proj_dirs.config_dir());
67    } else {
68        config.push(".");
69    }
70
71    // Make sure the directory exists, and create it if it does not.
72    DirBuilder::new().recursive(true).create(&config)?;
73    Ok(config)
74}
75
76/// Return the central configuration file.
77///
78/// If this file does not exist, it is created empty.
79pub fn get_config_file() -> std::io::Result<PathBuf> {
80    let mut path = get_config_directory()?;
81    path.push("hhh.config");
82    OpenOptions::new()
83        .write(true)
84        .create(true)
85        .open(path.clone())?;
86    Ok(path)
87}
88
89/// Configure logging.
90///
91/// This method should be called before any other logging method or
92/// macros are invoked to initialize the logging system.
93///
94/// This method uses the `env_logger` crate to initialize the logging
95/// system from the environment variables `HHH_LOG` and
96/// `HHH_LOG_STYLE`.
97pub fn configure_logging() {
98    // Configure logging based on environment variables.
99    let mut builder = env_logger::Builder::new();
100    builder.filter_level(log::LevelFilter::Warn);
101    let env = env_logger::Env::new()
102        .filter("HHH_LOG")
103        .write_style("HHH_LOG_STYLE");
104    builder.parse_env(env);
105    builder.init();
106}
107
108#[cfg(test)]
109mod lib_test {
110    use crate::{configure_logging, get_config_file};
111
112    #[test]
113    fn get_config_file_test() {
114        let file = get_config_file();
115        assert!(file.is_ok());
116    }
117
118    #[test]
119    fn configure_logging_test() {
120        configure_logging();
121    }
122}