use std::sync::{Arc, LazyLock};
use bytes::Bytes;
use futures::{Stream, StreamExt as _};
pub static RAND_BUFFER: LazyLock<Arc<Bytes>> = LazyLock::new(|| {
use rand::RngCore as _;
let mut buf = vec![0u8; 1024 * 1024]; rand::rng().fill_bytes(&mut buf);
Arc::new(Bytes::from(buf))
});
pub fn chunk_of(len: usize) -> Bytes {
let buf = RAND_BUFFER.clone();
if len <= buf.len() {
buf.slice(0..len)
} else {
let mut data = Vec::with_capacity(len);
while data.len() < len {
let n = (len - data.len()).min(buf.len());
data.extend_from_slice(&buf[0..n]);
}
Bytes::from(data)
}
}
pub fn download_stream(
total_size: usize,
chunk_size: usize,
) -> impl Stream<Item = std::result::Result<Bytes, std::io::Error>> {
let chunk_size = chunk_size.max(1);
let chunks = total_size.div_ceil(chunk_size);
futures::stream::iter(0..chunks).map(move |i| {
let bytes_sent = i * chunk_size;
let remaining = total_size.saturating_sub(bytes_sent);
let this_chunk = chunk_size.min(remaining);
Ok(chunk_of(this_chunk))
})
}