use core::ops::Deref;
use core::ptr::NonNull;
use crate::metal::PAGE_SIZE;
pub struct AlignedInput {
ptr: NonNull<u8>,
len: usize,
capacity: usize,
}
impl AlignedInput {
#[must_use]
pub fn from_slice(bytes: &[u8]) -> Self {
let capacity = bytes.len().next_multiple_of(PAGE_SIZE).max(PAGE_SIZE);
let layout = std::alloc::Layout::from_size_align(capacity, PAGE_SIZE)
.expect("page-aligned layout is always valid");
let ptr = unsafe { std::alloc::alloc(layout) };
let Some(ptr) = NonNull::new(ptr) else {
std::alloc::handle_alloc_error(layout);
};
unsafe {
std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr.as_ptr(), bytes.len());
std::ptr::write_bytes(ptr.as_ptr().add(bytes.len()), b' ', capacity - bytes.len());
}
Self {
ptr,
len: bytes.len(),
capacity,
}
}
#[must_use]
pub fn as_slice(&self) -> &[u8] {
unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
#[must_use]
pub fn len(&self) -> usize {
self.len
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub(crate) fn base_ptr(&self) -> NonNull<u8> {
self.ptr
}
}
impl Deref for AlignedInput {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.as_slice()
}
}
impl Drop for AlignedInput {
fn drop(&mut self) {
let layout = std::alloc::Layout::from_size_align(self.capacity, PAGE_SIZE)
.expect("layout validated at construction");
unsafe { std::alloc::dealloc(self.ptr.as_ptr(), layout) };
}
}
unsafe impl Send for AlignedInput {}
unsafe impl Sync for AlignedInput {}
impl std::fmt::Debug for AlignedInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AlignedInput")
.field("len", &self.len)
.field("capacity", &self.capacity)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_slice_is_aligned_padded_and_roundtrips() {
let input = AlignedInput::from_slice(b"{\"a\":1}");
assert_eq!(&*input, b"{\"a\":1}");
assert_eq!(input.len(), 7);
assert!(!input.is_empty());
assert_eq!(input.base_ptr().as_ptr() as usize % PAGE_SIZE, 0);
assert_eq!(input.capacity % PAGE_SIZE, 0);
let full =
unsafe { core::slice::from_raw_parts(input.base_ptr().as_ptr(), input.capacity) };
assert!(full[input.len()..].iter().all(|&b| b == b' '));
}
#[test]
fn empty_input_still_allocates_one_padded_page() {
let input = AlignedInput::from_slice(b"");
assert!(input.is_empty());
assert_eq!(input.capacity, PAGE_SIZE);
let full =
unsafe { core::slice::from_raw_parts(input.base_ptr().as_ptr(), input.capacity) };
assert!(full.iter().all(|&b| b == b' '));
}
#[test]
fn page_multiple_inputs_get_no_extra_page() {
let bytes = vec![b'7'; PAGE_SIZE];
let input = AlignedInput::from_slice(&bytes);
assert_eq!(input.capacity, PAGE_SIZE);
assert_eq!(input.len(), PAGE_SIZE);
}
#[test]
fn aligned_input_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<AlignedInput>();
}
}