#![deny(rust_2018_idioms)]
#![allow(clippy::single_component_path_imports)]
#![allow(clippy::type_complexity)]
#![cfg_attr(docsrs, allow(unused_attributes))]
#![recursion_limit = "1024"]
#![warn(
    missing_debug_implementations,
    missing_docs,
    rust_2018_idioms,
    unreachable_pub
)]
//! [![](https://gitlab.com/andrew_ryan/doe/-/raw/master/doe.svg)](https://docs.rs/doe)

#![doc(
    html_logo_url = "https://gitlab.com/andrew_ryan/doe/-/raw/master/html_logo.svg",
    html_favicon_url = "https://gitlab.com/andrew_ryan/doe/-/raw/master/html_favicon.svg"
)]

//!
//! doe is a versatile Rust crate that significantly enhances the development workflow by offering an extensive collection of useful macros and utility functions. It streamlines common tasks and provides convenient features for clipboard management, state management, keyboard input, and mouse interaction. Additionally, doe includes robust cryptographic functions, enabling developers to easily integrate secure encryption, decryption, and hashing capabilities into their applications, ensuring data integrity and confidentiality.
//!
//!
//! ### Available Features:
//!
//! | Feature      | Description                                      | Command                              |
//! |--------------|--------------------------------------------------|--------------------------------------|
//! | **ctf**      | String manipulation and encoding utilities       | `cargo add doe -F ctf`               |
//! | **clip**     | Clipboard management                             | `cargo add doe -F clip`              |
//! | **mouse**    | Mouse input simulation                           | `cargo add doe -F mouse`             |
//! | **keyboard** | Keyboard input simulation                        | `cargo add doe -F keyboard`          |
//! | **kcm**      | Keyboard, clipboard, and mouse combined          | `cargo add doe -F kcm`               |
//! | **xlsx**     | Excel file manipulation                          | `cargo add doe -F xlsx`              |
//! | **docx**     | Word document manipulation                       | `cargo add doe -F docx`              |
//! | **date**     | Date and time utilities                          | `cargo add doe -F date`              |
//! | **screenshot** | Screenshot capture and processing              | `cargo add doe -F screenshot`        |
//! | **images**   | Image manipulation                               | `cargo add doe -F images`            |
//! | **crypto**   | Cryptographic functions                          | `cargo add doe -F crypto`            |
//! | **asyncrs**  | Async runtime utilities                          | `cargo add doe -F asyncrs`           |
//! | **logger**   | Logging utilities                                | `cargo add doe -F logger`            |
//! | **sqlserver** | SQL Server database operations                  | `cargo add doe -F sqlserver`         |
//! | **axumserver** | Axum server utilities                          | `cargo add doe -F axumserver`        |
//! | **ip_addr**  | IP address utilities                             | `cargo add doe -F ip_addr`           |
//! | **http**     | HTTP client and server utilities                 | `cargo add doe -F http`              |
//! | **process**  | Process management utilities                     | `cargo add doe -F process`           |
//! | **json**     | JSON manipulation utilities                      | `cargo add doe -F json`              |
/// Async runtime utilities for concurrent programming
///
/// # Examples
///
/// ```ignore
/// #[allow(warnings)]
/// fn main() {
/// // Block on an async operation
/// asyncrs::block_on(async {
///     let output = asyncrs::command("echo hello").await;
///     println!("{}", String::from_utf8_lossy(&output.stdout));
/// });
///     let rt = doe::asyncrs::runtime::Builder::new_multi_thread()
///         .enable_all()
///         .build()
///         .unwrap();
///     rt.block_on(run());
///     rt.block_on(async {
///         run().await;
///     });
/// }
///
/// async fn run() {}
///
/// ```
pub mod asyncrs;
/// Clipboard operations for copying and pasting data
///
/// # Examples
///
/// ```ignore
///fn main()->doe::DynError<()> {
///    use doe::clipboard::get_clipboard;
///    use doe::clipboard::set_clipboard;
///    set_clipboard("rust").unwrap();
///    let clip = get_clipboard().unwrap();
///    assert_eq!("rust",clip);
///    Ok(())
///}
/// ```
pub mod clipboard;
/// Color format conversions between RGB and HEX
///
/// # Examples
///
/// ```ignore
/// use doe::color;
///
/// // Convert RGB to HEX
/// let hex = color::rgb_to_hex(255, 0, 0);
/// assert_eq!(hex, "#FF0000");
///
/// // Convert HEX to RGB
/// let (r, g, b) = color::hex_to_rgb("#00FF00").unwrap();
/// assert_eq!((r, g, b), (0, 255, 0));
/// ```
pub mod color;
/// Common constants used throughout the crate
///
/// # Examples
///
/// ```ignore
/// use doe::consts;
///
/// // Access predefined constants
/// println!("USER_AGENTS: {:?}", consts::USER_AGENTS);
/// ```
pub mod consts;
/// Cryptographic functions including AES, RSA, SHA, MD5 and Blake3
///
/// # Examples
///
/// ```ignore
/// use doe::crypto;
///
/// // AES Encryption/Decryption
/// let key = b"0123456789abcdef0123456789abcdef"; // 256-bit key
/// let iv = b"1234567890abcdef"; // 128-bit IV
/// let data = b"secret message";
///
/// let encrypted = crypto::aes::aes_cbc_encrypt(key, iv, data).unwrap();
/// let decrypted = crypto::aes::aes_cbc_decrypt(key, iv, &encrypted).unwrap();
/// assert_eq!(data, decrypted.as_slice());
///
/// // RSA Key Generation and Encryption
/// let (private_key, public_key) = crypto::rsa::generate_keypair(2048);
/// let encrypted = crypto::rsa::encrypt(&public_key, data).unwrap();
/// let decrypted = crypto::rsa::decrypt(&private_key, &encrypted).unwrap();
/// assert_eq!(data, decrypted.as_slice());
///
/// // Hashing
/// let hash = crypto::sha256::hash(data);
/// println!("SHA-256 hash: {:x}", hash);
/// ```
pub mod crypto;
/// ctf module provides utility functions like `permutations`,`hex_encode`,`hex_decode`,`base64_encode`,`base64_decode`,`php_urlencode`,`php_urldecode`.
/// convert_to_pinyin_with_non_chinese
///```ignore
/// use doe::ctf::*;
/// convert_to_pinyin_with_non_chinese("ctf 我来测试一下 this code").dprintln();//ctf_wo_lai_ce_shi_yi_xia_this_code
///```
///
///contains_chinese
///```ignore
///contains_chinese("span测试").dprintln();//true
///contains_chinese("span").dprintln();//false
///```
///parse_html
///```ignore
///parse_html(html,"span", None).dprintln();//find all span
///parse_html(html,"h2", Some("id")).dprintln(); //find all h2 and get id value
///```
pub mod ctf;
/// date module contains functions for get now,get_recent_seven_days,normal_date_to_excel_date,excel_date_to_normal_date
/// # Examples
///
/// ```ignore
/// use doe::date;
/// let normal_date = date::excel_date_to_normal_date(45292).unwrap();
/// println!("Normal date: {}", normal_date);
/// ```
/// ```ignore
/// use doe::date;
/// let excel_date = date::normal_date_to_excel_date("2023-10-01").unwrap();
/// println!("Excel date: {}", excel_date);
/// ```
/// ```ignore
/// use doe::date;
/// let recent_dates = date::get_recent_seven_days();
/// for date in recent_dates {
///     println!("{}", date);
/// }
/// ```
pub mod date;
///xlsx module contains functions for reading editing docx file
/// docx_replace
///
/// finds all 'name' and replace with 'andrew'
/// ```ignore
///use doe::*;
///docx::docx_replace("./name.docx","name","andrew").unwrap();
/// ```
pub mod docx;
/// The file system (fs) module provides functions and structs for performing operations on the file system. It includes functions for reading, writing, creating, and deleting files and directories.
///## useage of fs module
///```ignore
///fn main() {
///    use doe::*;
///    use doe::DebugPrint;
///    use doe::Str;
///    use std::ops::Deref;
///    // append data to file
///    append_data_to_file("demo.txt", "demo".as_bytes().to_vec()).unwrap();
///
///    // get all files and folders
///    walk_dir(".".to_path().deref()).unwrap().dprintln();
///
///    // get all folders
///    walk_dir_get_files(".".to_path().deref()).unwrap().dprintln();
///
///    // get all folders
///    walk_dir_get_folders(".".to_path().deref())
///        .unwrap()
///        .dprintln();
///
///    //move file the directory to a new directory
///    move_file(
///        "/Users/ryanandrew/code/test/t1/demo.zip".to_path().deref(),
///        "/Users/ryanandrew/code/test/t2/d2.zip".to_path().deref(),
///    )
///    .unwrap();
///
///    //copy file the directory to a new directory
///    copy_file(
///        "/Users/ryanandrew/code/test/t1/demo.zip".to_path().deref(),
///        "/Users/ryanandrew/code/test/t2/d2.zip".to_path().deref(),
///    )
///    .unwrap();
///    //move all files in the directory to a new directory
///    move_folder(
///        "/Users/ryanandrew/code/test/t1".to_path().deref(),
///        "/Users/ryanandrew/code/test/t2/t1".to_path().deref(),
///    )
///    .unwrap();
///
///    //copy all files in the directory to a new directory
///    copy_folder(
///        "/Users/ryanandrew/code/test/d1".to_path().deref(),
///        "/Users/ryanandrew/code/test/d2".to_path().deref(),
///    )
///    .unwrap();
///}
///```
pub mod fs;
///reqwest module is easy way to use reqwest crate for http requests
/// # Examples
///
/// ```
/// use doe::httprs;
///
/// // Create a client with custom headers
/// let headers = httprs::headers![
///     "Content-Type" => "application/json",
///     "Authorization" => "Bearer token"
/// ];
///
/// // Make a GET request
/// let client = httprs::sync_client_with_headers(headers);
/// let response = client.sync_get_bytes("https://api.example.com/data");
/// ```
pub mod httprs;
///images module contains functions resize add paddings,convert image format
/// ```ignore
/// use doe::images::image_add_padding;
/// image_add_padding(
///     "demo.png",
///     [255,255,255,255], 10,
///     10,
///     "new_demo.png"
/// );
/// ````
pub mod images;
/// IP address parsing and manipulation utilities
///
/// # Examples
///
/// ```ignore
/// use doe::ip_addr;
///
/// // Parse IP address
/// let ip = ip_addr::parse("192.168.1.1").unwrap();
/// println!("Parsed IP: {:?}", ip);
///
/// // Check if IP is private
/// if ip_addr::is_private(&ip) {
///     println!("This is a private IP address");
/// }
///
/// // Convert to CIDR notation
/// let cidr = ip_addr::to_cidr(&ip, 24);
/// println!("CIDR: {}", cidr);
/// ```
pub mod ip_addr;
///json module contains functions for reading, writing, and manipulating JSON files or content.
///```ignore
///let data = json!({
///    "user_id": 89579,
///    "auth_password": "dW5kZWZpbmVk",
///    "blockchain": false,
///    "blockchain_token_all": 10000,
///    "blockchain_init_token": null
///});
///let json_bytes:Vec<u8> = data.as_bytes();
/// ```
/// ```ignore
/// let r = r#"
/// {
///     "user_id": 89579,
///     "auth_password": "dW5kZWZpbmVk",
///     "blockchain": false,
///     "blockchain_token_all": 10000,
///     "blockchain_init_token": null
/// }
/// "#.trim();
/// let value = r.to_json_value();
/// ```
pub mod json;
///keyboard module contains functions and structs related to keyboard input. It allows the user to simulate keyboard input, capture keystrokes, and perform other keyboard-related operations.
/// ## keyboard example
/// ```ignore
/// //cargo add doe -F kcm
///use doe::keyboard::key_click;
///use doe::keyboard::key_press;
///use doe::keyboard::key_release;
///use doe::keyboard::KeyCode;
///use doe::mouse::mouse_drag;
///use doe::mouse::move_to_paste;
///use doe::mouse::move_to_press_left;
///use doe::*;
///use keyboard::exit_if_click_esc;
///let list = vec!["iphone","ipad","macbook"];
///
///// crete new baogao
///move_to_press_left(857, 588).sleep(1.0); //#000000
///
///// create fengmian
///move_to_paste(1540, 853, "Apple").sleep(1.0); //#000000
///move_to_paste(1360, 882, "ID").sleep(1.0); //#000000
///
///// add shuoming
///move_to_paste(772, 464, "Discription").sleep(1.0); //#ffffff
///mouse_drag((894, 719).into(), (821, 716).into()).sleep(1.0); //#f0f0f0
///key_click("2024-01-23").sleep(1.0);
///move_to_press_left(740, 305).sleep(1.0); //#f0f0f0
///
///for name in list {
///    // add baobao
///    move_to_press_left(476, 253).sleep(1.0); //#ffffff
///
///    // name
///    move_to_press_left(796, 331).sleep(1.0); //#ffffff
///    key_click("end");
///    key_click("shift+home");
///    set_clipboard(name).unwrap().sleep(0.5);
///    key_click("ctrl+v");
///
///    // add fujian
///    move_to_press_left(870, 587).sleep(1.0); //#000000
///    mouse_drag((893, 818).into(), (814, 816).into()).sleep(1.0); //#f0f0f0
///    key_click("2024-01-23").sleep(1.0);
///    move_to_press_left(723, 206).sleep(1.0); //#000000
///}
///
///// set taoshu
///move_to_paste(1341, 910, "New_name").sleep(1.0); //#000000
/// ```
pub mod keyboard;
///logger module contains functions for logging
/// ```ignore
/// fn main() {
///     use doe::logger::*;
///     doe::logger::init();
///     debug!("hello world");
///     info!("hello world");
///     warn!("hello world");
/// }
/// ```
pub mod logger;
///exiftool module contains all utility macros for development
pub mod exiftool;
///macros module contains all utility macros for development
pub mod macros;
/// mouse module contains functions and structs related to mouse input. It allows the user to simulate mouse input, capture mouse movements and clicks, and perform other mouse-related operations.
/// ```ignore
///fn main()->doe::DynError<()> {
///    use std::time::Duration;
///    use doe::mouse::press;
///    move_to(300, 700);
///    press("left");
///    move_to_with_duration(0, 0,Duration::from_secs(5));
///    move_and_press_right(800,900);
///    press("right");
///    Ok(())
///}
///```
pub mod mouse;
/// get all process (name,pid) and kill process by name or pid
/// # Examples
///
/// ```ignore
/// let processes: Vec<ProcessInfo> = get_all_process_name_and_pid();
/// for process in processes {
///     println!("Process ID: {}, Name: {}", process.pid, process.name);
/// }
/// ```
pub mod process;
/// Random number generation using Linear Congruential Generator (LCG)
///
/// # Examples
///
/// ```ignore
/// use doe::rand;
///
/// // Create a new LCG instance
/// let mut rng = rand::LCG::new();
///
/// // Generate random numbers
/// let random_value = rng.random();
/// println!("Random value: {}", random_value);
/// ```
pub mod rand;
///screenshot module contains functions for screenshot and get hex from screenshot image
/// ```
/// use doe::screenshot;
///
/// let is_color_match = screenshot::screen_position_is((10, 10), "#FFFFFF");
/// println!("Color match: {}", is_color_match);
/// ```
/// ```
/// use doe::screenshot;
///
/// let rgb = screenshot::get_rgb_from_position("screenshot_0.png", 10, 10).unwrap();
/// println!("RGB: {:?}", rgb);
/// ```
pub mod screenshot;
/// SQL Server database operations including connection management and query execution
///
/// # Examples
///
/// ```ignore
/// use doe::sqlserver;
/// use deadpool_tiberius::Pool;
///
/// async fn example(pool: Pool) {
///     let result = sqlserver::run_sql_get_csv(
///         pool,
///         "SELECT * FROM users WHERE id = ?",
///         vec!["1".to_string()],
///     ).await.unwrap();
///     println!("Query result: {:?}", result);
/// }
/// ```
pub mod sqlserver;
///structs module contains definitions of custom data structures like `Bfn`, `Bts`, `waker_fn`.
///
/// # Examples
///
/// ```ignore
/// use doe::structs;
///
/// // Create a new Bfn instance
/// let bfn = structs::Bfn::new();
///
/// // Use Bfn for file operations
/// bfn.write("data.txt", "Hello World").unwrap();
/// let content = bfn.read("data.txt").unwrap();
/// assert_eq!(content, "Hello World");
/// ```
pub mod structs;
/// generate random number with sys fn
/// Here's a markdown documentation for the `sys_random` module:
///
/// # System Random Module
///
/// This module provides cryptographically secure random number generation functionality for both Windows and Linux systems.
///
/// ## Features
///
/// - Generate cryptographically secure random bytes
/// - Generate version 4 UUIDs (random-based)
///
/// ## Requirements
///
/// Enable the `sys_random` feature to use this module.
///
/// ## Functions
///
/// ### `get_system_random_bytes(buffer: &mut [u8]) -> io::Result<()>`
///
/// Fills the provided buffer with cryptographically secure random bytes.
///
/// **Parameters:**
/// - `buffer`: A mutable byte slice to be filled with random data
///
/// **Returns:**
/// - `Ok(())` on success
/// - `Err(io::Error)` if the operation fails
///
/// **Example:**
/// ```rust
/// let mut buffer = [0u8; 32];
/// get_system_random_bytes(&mut buffer).unwrap();
/// ```
///
/// ### `uuid() -> String`
///
/// Generates a random version 4 UUID (Universally Unique Identifier) according to RFC 4122.
///
/// **Returns:**
/// - A string representation of the UUID in the format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
///
/// **Example:**
/// ```rust
/// let id = uuid();
/// println!("Generated UUID: {}", id);
/// // Example output: "550e8400-e29b-41d4-a716-446655440000"
/// ```
///
/// ## Platform Support
///
/// ### Windows
/// Uses the CryptoAPI through:
/// - `CryptAcquireContextA`
/// - `CryptGenRandom`
/// - `CryptReleaseContext`
///
/// ### Linux
/// Uses the `getrandom` system call.
///
/// ## Examples
///
/// ### Basic Usage
/// ```rust
/// use your_crate::sys_random;
///
/// fn main() {
///     // Generate random bytes
///     let mut random_data = [0u8; 16];
///     sys_random::get_system_random_bytes(&mut random_data).unwrap();
///     
///     // Generate a UUID
///     let uuid = sys_random::uuid();
///     println!("Random UUID: {}", uuid);
/// }
/// ```
///
/// ### Error Handling
/// ```rust
/// use your_crate::sys_random;
/// use std::io;
///
/// fn get_random_data() -> io::Result<[u8; 32]> {
///     let mut buffer = [0u8; 32];
///     sys_random::get_system_random_bytes(&mut buffer)?;
///     Ok(buffer)
/// }
/// ```
///
/// ## Testing
///
/// The module includes basic tests to verify functionality:
/// ```rust
/// #[test]
/// fn test_get_system_random_bytes() {
///     let mut buffer = [0u8; 16];
///     assert!(get_system_random_bytes(&mut buffer).is_ok());
/// }
/// ```
///
/// ## Notes
///
/// - The UUID generation follows version 4 specifications (random-based)
/// - The random number generators used are cryptographically secure
/// - On Linux, this uses the `getrandom` system call which blocks if the CSPRNG hasn't been initialized yet
/// - On Windows, this uses the CryptoAPI which is available on all modern Windows versions
pub mod sys_random;
/// timer module provides functions and structs for creating and managing timers. It allows the user to schedule tasks to be executed at a specific time or interval.
/// ```ignore
/// use doe::run_timer;
/// fn run(){
///     println!("running ");
///}
///   run_timer(std::time::Instant::now(),std::time::Duration::from_secs(1),std::time::Duration::from_secs(5),Box::new(run));
///
/// ```
pub mod timer;
///traits module contains trait definitions that define shared behavior and functions
///
/// # Examples
///
/// ```ignore
/// use doe::traits;
///
/// // Implement custom trait
/// struct MyStruct;
/// impl traits::MyTrait for MyStruct {
///     fn do_something(&self) {
///         println!("Doing something!");
///     }
/// }
///
/// let my_struct = MyStruct;
/// my_struct.do_something();
/// ```
pub mod traits;
///xlsx module contains functions and structs for reading, writing, and manipulating Excel files in the XLSX format.
///```ignore
///use doe::*;
///xlsx::xlsx_set_values("./demo.xlsx", "Sheet1", &[cellvalue!("M4", "3", "number")]);
/// ```
pub mod xlsx;
///zoml module contains functions for converting data between the ZOML format and CSV format.
///
/// # Examples
///
/// ```ignore
/// use doe::zoml;
///
/// // Convert CSV to ZOML
/// let csv_data = "name,age\nAlice,30\nBob,25";
/// let zoml_data = zoml::csv_to_zoml(csv_data).unwrap();
///
/// // Convert ZOML back to CSV
/// let converted_csv = zoml::zoml_to_csv(&zoml_data).unwrap();
/// assert_eq!(csv_data, converted_csv);
/// ```
pub mod zoml;

/// Axum web server utilities for building HTTP APIs
///
/// # Examples
///
/// ```ignore
/// use doe::axumserver;
/// use axum::{routing::get, Router};
///
/// #[tokio::main]
/// async fn main() {
///     // Create router with routes
///     let app = Router::new()
///         .route("/", get(|| async { "Hello from Axum!" }));
///     
///     // Start server
///     axumserver::start_server("127.0.0.1:3000", app).await;
/// }
/// ```
pub mod axumserver;

pub use consts::consts::*;
pub use fs::fs::*;
pub use macros::macros::*;
pub use rand::rand::*;
pub use structs::structs::*;
pub use timer::impl_timer::*;
pub use traits::traits::*;
pub use zoml::zoml::*;

use std::sync::Arc;
/// Rust is a wrapper for the standard library's std::error::Error trait, which is used to define the behavior of types that can be used for error handling. It provides a way to represent errors in a consistent and type-safe manner.
pub type DynError<T> = Result<T, Box<dyn std::error::Error>>;
///Rust is a wrapper for the standard library's std::process::Command function, which is used to execute external commands
///```ignore
///     doe::system("ls");
///     doe::system("ls -a");
/// ```
///
/// # Examples
///
/// ```ignore
/// use doe::system;
/// system("ls -a");
/// ```
pub fn system(command: impl ToString) -> std::io::Result<()> {
    use std::process::Command;
    if cfg!(target_os = "windows") {
        if crate::has_powershell!() {
            Command::new("powershell")
                .arg("-Command")
                .arg(&command.to_string())
                .status()?;
        } else {
            Command::new("cmd")
                .arg("/c")
                .arg(&command.to_string())
                .status()?;
        }
    } else {
        Command::new("sh")
            .arg("-c")
            .arg(&command.to_string())
            .status()?;
    }
    Ok(())
}
///CommandOut struct is used to store the output and error of a command execution.
#[derive(Debug,Default)]
pub struct CommandOut{
    ///stdout is the standard output of the command execution.
    pub stdout: String,
    ///error is the standard error of the command execution.
    pub stderr: String,
    ///status is the exit status of the command execution.
    pub status: std::process::ExitStatus,
}

///
#[cfg(not(target_arch = "wasm32"))]
pub fn command(command: impl ToString) -> std::io::Result<CommandOut> {
    let command = command.to_string();
    std::process::Command::run(&command)
}

///CommandHelper trait is used to run external commands and return their output and error.
pub trait CommandHelper {
    ///run command and return output and error
    fn run(command: impl ToString) -> std::io::Result<CommandOut>;
}

///CommandHelper trait is implemented for std::process::Command.
impl CommandHelper for std::process::Command {
    fn run(command: impl ToString) -> std::io::Result<CommandOut> {
        let command = command.to_string();
        use std::process::Command;
        let output = if cfg!(target_os = "windows") {
            if crate::has_powershell!() {
                Command::new("powershell")
                    .arg("-Command")
                    .arg(&command.to_string())
                    .output()?
            } else {
                Command::new("cmd")
                    .arg("/c")
                    .arg(&command.to_string())
                    .output()?
            }
        } else {
            Command::new("sh")
                .arg("-c")
                .arg(&command.to_string())
                .output()?
        };
        let stdout = output.stdout.to_string_lossy();
        let stderr = output.stderr.to_string_lossy();
        Ok(CommandOut{stdout, stderr, status: output.status})
    }
}

///lowercase_letters
pub fn lowercase_letters() -> Arc<str> {
    Arc::from("abcdefghijklmnopqrstuvwxyz")
}
///uppercase_letters
pub fn uppercase_letters() -> Arc<str> {
    Arc::from("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
}
///digits
pub fn digits() -> Arc<str> {
    Arc::from("0123456789")
}
///letters_and_digits
pub fn letters_and_digits() -> Arc<str> {
    Arc::from(format!("{}{}{}", lowercase_letters(), uppercase_letters(), digits()).as_ref())
}

///The Vec sort all elements can be repeated to define the longest shortest size
/// ```ignore
///fn main() {
///     use doe::DebugPrint;
///     use doe::utils::generate_all_possible_vec;
///    let v  = generate_all_possible_vec(&vec![1,2,3],1,2);
///    v.dprintln();//[[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]]
///}
///```
pub fn generate_all_possible_vec<T: Clone>(
    elements: &[T],
    min_len: usize,
    max_len: usize,
) -> Vec<Vec<T>> {
    let mut result = Vec::new();
    for len in min_len..=max_len {
        let mut indices = vec![0; len];
        let mut done = false;
        while !done {
            let permutation = indices.iter().map(|&i| elements[i].clone()).collect();
            result.push(permutation);
            done = true;
            for i in (0..len).rev() {
                indices[i] += 1;
                if indices[i] == elements.len() {
                    indices[i] = 0;
                } else {
                    done = false;
                    break;
                }
            }
        }
    }
    result
}
///permutations
/// ```ignore
///fn main() {
///    use doe::utils::permutations;
///    use doe::DebugPrint;
///    permutations("abc").dprintln();//["abc", "acb", "bac", "bca", "cba", "cab"]
///}
/// ```
pub fn permutations(alphabet: &str) -> Vec<String> {
    fn permute(chars: &mut [char], start: usize, result: &mut Vec<String>) {
        if start == chars.len() {
            result.push(chars.iter().collect());
        } else {
            for i in start..chars.len() {
                chars.swap(start, i);
                permute(chars, start + 1, result);
                chars.swap(start, i);
            }
        }
    }

    let mut result = Vec::new();
    let mut chars: Vec<char> = alphabet.chars().collect();
    permute(&mut chars, 0, &mut result);
    result
}

#[derive(Debug, Clone, Default)]
/// CommandResult
pub struct CommandResult {
    #[allow(dead_code)]
    ///stderr
    pub stderr: Box<str>,
    #[allow(dead_code)]
    ///stderr_size
    pub stdout: Box<str>,
    ///executed
    pub executed: bool,
    /// status
    pub status: bool,
}
/// max_cmd_output_size
pub const MAX_CMD_OUTPUT_SIZE: usize = 1 << 15;

/// execute_command
///
/// ```ignore
/// use doe::execute_command;
/// let result = execute_command("nasm".as_ref(), &["-version".as_ref()]);
/// println!("{:?}",result);
/// ```
///
///
pub fn execute_command(executable: &std::ffi::OsStr, args: &[&std::ffi::OsStr]) -> CommandResult {
    if let std::result::Result::Ok(mut result) =
        std::process::Command::new(executable).args(args).output()
    {
        result.stderr.truncate(MAX_CMD_OUTPUT_SIZE);
        let stderr = String::from_utf8(result.stderr)
            .unwrap_or_default()
            .into_boxed_str();
        result.stdout.truncate(MAX_CMD_OUTPUT_SIZE);
        let stdout = String::from_utf8(result.stdout)
            .unwrap_or_default()
            .into_boxed_str();
        return CommandResult {
            stderr,
            stdout,
            executed: true,
            status: result.status.success(),
        };
    }
    CommandResult {
        stderr: String::new().into_boxed_str(),
        stdout: String::new().into_boxed_str(),
        executed: false,
        status: false,
    }
}
