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}