use std::num::NonZero;
use crate::BytesBuf;
use crate::mem::testing::std_alloc_block;
use crate::mem::{BlockSize, Memory};
#[derive(Clone, Debug, Default)]
pub struct TransparentMemory {
_placeholder: (),
}
impl TransparentMemory {
#[must_use]
pub const fn new() -> Self {
Self { _placeholder: () }
}
#[must_use]
#[expect(clippy::unused_self, reason = "for potential future functionality enrichment")]
pub fn reserve(&self, len: usize) -> crate::BytesBuf {
reserve(len)
}
}
impl Memory for TransparentMemory {
#[cfg_attr(test, mutants::skip)] fn reserve(&self, min_bytes: usize) -> crate::BytesBuf {
self.reserve(min_bytes)
}
}
fn reserve(min_bytes: usize) -> crate::BytesBuf {
let Some(min_bytes) = NonZero::new(min_bytes) else {
return BytesBuf::default();
};
let block_count = min_bytes.get().div_ceil(BlockSize::MAX as usize);
let mut bytes_remaining = min_bytes.get();
let mut blocks = Vec::with_capacity(block_count);
for _ in 0..block_count {
#[expect(
clippy::cast_possible_truncation,
reason = "the usize never contains a value outside bounds of BlockSize - guarded by min()"
)]
let bytes_in_block = NonZero::new(bytes_remaining.min(BlockSize::MAX as usize) as BlockSize)
.expect("ran out of bytes before calculated block count - the math must be wrong");
bytes_remaining = bytes_remaining
.checked_sub(bytes_in_block.get() as usize)
.expect("negative bytes remaining - algorithm error");
blocks.push(std_alloc_block::allocate(bytes_in_block));
}
BytesBuf::from_blocks(blocks)
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use static_assertions::assert_impl_all;
use super::*;
use crate::mem::MemoryShared;
assert_impl_all!(TransparentMemory: MemoryShared);
#[test]
fn smoke_test() {
let memory = TransparentMemory::new();
let mut buf = memory.reserve(0);
assert_eq!(buf.len(), 0);
assert_eq!(buf.capacity(), 0);
buf = memory.reserve(1313);
assert_eq!(buf.capacity(), 1313);
buf.put_byte_repeated(3, 1313);
let data = buf.consume_all();
assert_eq!(data.len(), 1313);
assert_eq!(data.first_slice().len(), 1313);
}
#[test]
fn giant_allocation() {
#[cfg(all(not(miri), any(target_os = "linux", target_os = "windows")))]
if crate::testing::system_memory() < 10_000_000_000 {
eprintln!("Skipping giant allocation test due to insufficient memory.");
return;
}
let memory = TransparentMemory::new();
let buf = memory.reserve(5_000_000_000);
assert_eq!(buf.capacity(), 5_000_000_000);
}
}