/*
==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--

Dia-Files

Copyright (C) 2019-2024  Anonymous

There are several releases over multiple years,
they are listed as ranges, such as: "2019-2024".

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--::--
*/

//! # Dia-Files
//!
//! ## Project
//!
//! - License: GNU Lesser General Public License, either version 3, or (at your option) any later version.
//! - _This project follows [Semantic Versioning 2.0.0]_
//!
//! ## Features
//!
//! - Finding files recursively: [`find_files()`][::find_files()].
//! - And some functions for reading bytes from [`Read`][r://Read], [`Path`][r://Path]...
//!
//! ## Notes
//!
//! - Tests require some symbolic link files in `tests/` directory. At the time of writing this note, Cargo does not allow publishing crates
//!   containing symbolic link files. So for source publishing on <https://crates.io/crates/dia-files>, they are stripped. However, the
//!   repository has all those files.
//!
//! - Documentation is built with all features. Some of them are optional. If you see components from other crates, you can view source to see
//!   what features are required.
//!
//! [Semantic Versioning 2.0.0]: https://semver.org/spec/v2.0.0.html
//!
//! [::find_files()]: fn.find_files.html
//! [r://Read]: https://doc.rust-lang.org/std/io/trait.Read.html
//! [r://Path]: https://doc.rust-lang.org/std/path/struct.Path.html

#![warn(missing_docs)]

#![feature(doc_cfg)]

// ╔═════════════════╗
// ║   IDENTIFIERS   ║
// ╚═════════════════╝

macro_rules! code_name  { () => { "dia-files" }}
macro_rules! version    { () => { "0.21.0" }}

/// # Crate name
pub const NAME: &str = "Dia-Files";

/// # Crate code name
pub const CODE_NAME: &str = code_name!();

/// # ID of this crate
pub const ID: &str = concat!(
    "4026816f-f9aa2c43-932ab1fd-2ec6adbd-1f288e5d-6b8b2ab7-0ed2e589-ae211f06-",
    "0cd6923c-0ce42168-355a8795-4450b615-6439a1c9-cf2bb0e7-f966c980-060f1a13",
);

/// # Crate version
pub const VERSION: &str = version!();

/// # Crate release date (year/month/day)
pub const RELEASE_DATE: (u16, u8, u8) = (2024, 4, 18);

/// # Tag, which can be used for logging...
pub const TAG: &str = concat!(code_name!(), "::4026816f::", version!());

// ╔════════════════════╗
// ║   IMPLEMENTATION   ║
// ╚════════════════════╝

#[cfg(feature="libc")]
extern crate alloc;

/// # Wrapper for format!(), which prefixes your optional message with: crate::TAG, module_path!(), line!()
macro_rules! __ {
    ($($arg: tt)+) => {
        format!("[{tag}][{module_path}-{line}] {msg}", tag=crate::TAG, module_path=module_path!(), line=line!(), msg=format!($($arg)+))
    };
    () => {
        format!("[{tag}][{module_path}-{line}] (internal error)", tag=crate::TAG, module_path=module_path!(), line=line!())
    };
}

/// # Makes new std::io::Error
macro_rules! err {
    ($kind: path, $($arg: tt)+) => { std::io::Error::new($kind, __!($($arg)+)) };
    ($($arg: tt)+) => { err!(std::io::ErrorKind::Other, $($arg)+) };
    () => { std::io::Error::new(std::io::ErrorKind::Other, __!()) };
}

macro_rules! async_call { ($f: expr) => {{
    #[cfg(feature="async-std")]
    let r = $f.await;
    #[cfg(not(feature="async-std"))]
    let r = $f;
    r
}}}

#[test]
fn test_crate_version() {
    assert_eq!(VERSION, env!("CARGO_PKG_VERSION"));
}

pub mod debts;
pub mod filter;
pub mod version_info;

mod file_system;
mod limit;
mod path_ext;
mod permissions;
mod root;
mod sealed;

pub use self::{
    file_system::*,
    limit::*,
    path_ext::*,
    permissions::*,
    root::*,
};

pub (crate) use self::sealed::*;

/// # Result type used in this crate
pub type Result<T> = std::result::Result<T, std::io::Error>;
