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

Zeros

Copyright (C) 2019-2025  Anonymous

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

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/>.

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

//! # Zeros
//!
//! ## 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
//!
//! This project provides:
//!
//! -   _Some_ [hash functions][mod:keccak] from [Keccak][site:keccak].
//! -   Some cryptographic implementations: [Chacha][mod:chacha], [Poly1305][mod:poly1305], [Argon2][mod:argon2]...
//!
//! ## Notes
//!
//! -   Currently only little-endian systems are supported. We don't have access or knowledge to test on big-endian systems.
//! -   Internal state stores data on [`u64`]. So it works best on systems supporting `u64` natively.
//! -   Accuracy/correctness is highest priority. Speed is second. Currently, it's slower than well-known implementations, such as
//!     [OpenSSL][site:openssl].
//! -   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.
//! -   Night Rust is required to build.
//!
//! [Semantic Versioning 2.0.0]: https://semver.org/spec/v2.0.0.html
//!
//! [site:keccak]: https://keccak.team
//! [site:openssl]: https://www.openssl.org
//!
//! [mod:argon2]: argon2/index.html
//! [mod:chacha]: chacha/index.html
//! [mod:keccak]: keccak/index.html
//! [mod:poly1305]: poly1305/index.html

#![warn(missing_docs)]
#![no_std]

#![cfg_attr(feature="simd", feature(portable_simd))]

#![feature(bigint_helper_methods)]
#![feature(doc_cfg)]
#![feature(test)]

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

macro_rules! code_name  { () => { "zeros" }}
macro_rules! version    { () => { "17.3.2" }}

/// # Crate name
pub const NAME: &str = "Zeros";

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

/// # ID of this crate
pub const ID: &str = concat!(
    "85ede580-25ef8822-72185cb5-6608f8ae-3c960bc1-75e3ab78-6d1f8a8a-55eb5c40-",
    "f0b681d6-13275f82-d587a89e-9de72f64-3951a1b0-79f48b29-de4a6330-817a600f",
);

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

/// # Crate release date (year/month/day)
pub const RELEASE_DATE: (u16, u8, u8) = (2025, 6, 5);

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

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

#[macro_use]
extern crate alloc;

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

#[cfg(test)]
extern crate test;

/// # Makes new Error
macro_rules! e {
    () => {
        $crate::Error::new(line!(), module_path!(), None)
    };
    ($($s: tt)+) => {
        $crate::Error::new(line!(), module_path!(), Some(alloc::borrow::Cow::Borrowed(concat!($($s)+))))
    };
}

/// # Makes new Error
macro_rules! err {
    ($($arg: tt)*) => {
        $crate::Error::new(line!(), module_path!(), Some(alloc::borrow::Cow::Owned(alloc::format!($($arg)*))))
    };
}

#[test]
fn test_macro_err() {
    use alloc::borrow::Cow;

    macro_rules! s_test { () => { "test" }}

    fn eq(first: Error, second: Error) -> bool {
        first.line() == second.line() && first.module_path() == second.module_path() && first.msg() == second.msg()
    }

    assert!(eq(e!(), Error::new(line!(), module_path!(), None)));
    assert!(eq(e!(s_test!(), s_test!()), Error::new(line!(), module_path!(), Some(Cow::Borrowed(concat!(s_test!(), s_test!()))))));
    assert!(eq(e!("test"), Error::new(line!(), module_path!(), Some(Cow::Borrowed(s_test!())))));
    assert!(eq(err!("{s:?}", s=s_test!()), Error::new(line!(), module_path!(), Some(Cow::Owned(alloc::format!("{:?}", s_test!()))))));

    let some = "===";
    assert_eq!(err!("{some}").msg(), Error::new(line!(), module_path!(), Some(Cow::Borrowed(some))).msg());
}

#[macro_use]
mod error;

mod bytes;
mod str;
mod zeros;

pub mod argon2;
pub mod chacha;
pub mod io;
pub mod keccak;
pub mod poly1305;
pub mod prg;
pub mod version_info;

pub use crate::{
    bytes::*,
    error::*,
    zeros::*,
};

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

/// # Result for I/O functions
#[cfg(feature="std")]
#[doc(cfg(feature="std"))]
pub type IoResult<T> = core::result::Result<T, std::io::Error>;

#[cfg(all(feature="std", test))]
const TEST_LOOPS: usize = 999;

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