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

sluggish-write

Copyright (C) 2026  Anonymous



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

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

use {
    sluggish_write::{BigBuf, Result, SluggishRead},
    zeros::keccak::Hash,
};

#[cfg(not(feature="tokio"))]
use std::io::{self, Read};

#[cfg(feature="tokio")]
use tokio::{
    io::{self, AsyncReadExt},
    runtime::Runtime,
};

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

const HASH: Hash = Hash::Sha3_512;

macro_rules! run { () => {{
    for big_buf in BigBuf::all() {
        let data = big_buf.make()?;
        let data_hash = HASH.hash(&data);
        let mut sluggish_read = SluggishRead::new(data.as_slice());
        let mut keccak = HASH.new_keccak();
        assert_eq!(data_hash, loop {
            let mut buf = [u8::MIN; 8192];
            match async_call!(sluggish_read.read(&mut buf))? {
                usize::MIN => break keccak.finish(),
                read => keccak.update(&buf[..read]),
            };
        });
    }
    Ok(())
}}}

#[test]
#[cfg(not(feature="tokio"))]
fn tests() -> Result<()> {
    run!()
}

#[test]
#[cfg(feature="tokio")]
fn tests() -> Result<()> {
    Runtime::new()?.block_on(async move {
        run!()
    })
}
