extern crate alloc;
use core::{mem, ptr, slice, str};
#[repr(C)]
#[derive(Debug)]
pub struct StringPtr {
ptr: ptr::NonNull<u8>,
}
const _: () = assert!(
mem::align_of::<StringPtr>() == mem::size_of::<u64>(),
"struct StringPtr is not aligned to 64 bits!"
);
const _: () = assert!(
mem::size_of::<StringPtr>() == mem::size_of::<u64>(),
"struct StringPtr has size != 64 bits"
);
fn array_layout<T>(len: usize) -> core::alloc::Layout {
core::alloc::Layout::array::<T>(len)
.expect("Error: constructing an array layout for TokenString failed!")
}
impl From<&[u8]> for StringPtr {
fn from(value: &[u8]) -> Self {
let ptr = if value.is_empty() {
ptr::NonNull::dangling()
} else {
let s = value.len();
let l = array_layout::<u8>(s);
let raw = unsafe { alloc::alloc::alloc(l) };
let Some(not_null) = ptr::NonNull::new(raw) else {
alloc::alloc::handle_alloc_error(l)
};
unsafe {
ptr::copy_nonoverlapping(value.as_ptr(), not_null.as_ptr(), s);
}
not_null
};
Self { ptr }
}
}
unsafe impl Send for StringPtr {}
unsafe impl Sync for StringPtr {}
impl StringPtr {
#[cfg_attr(test, mutants::skip)]
pub fn drop_manually(&mut self, len: usize) {
if len > 0 {
unsafe {
alloc::alloc::dealloc(
self.ptr.as_ptr(),
array_layout::<u8>(len),
);
}
}
}
pub fn clone_manually(&self, len: usize) -> Self {
let ptr = if len == 0 {
ptr::NonNull::dangling()
} else {
let l = array_layout::<u8>(len);
let raw = unsafe { alloc::alloc::alloc(l) };
let Some(not_null) = ptr::NonNull::new(raw) else {
alloc::alloc::handle_alloc_error(l)
};
unsafe {
ptr::copy_nonoverlapping(
self.ptr.as_ptr(),
not_null.as_ptr(),
len,
);
}
not_null
};
Self { ptr }
}
pub(crate) fn copy_manually(&mut self, idx: usize, value: &[u8]) {
unsafe {
ptr::copy_nonoverlapping(
value.as_ptr(),
self.ptr.as_ptr().add(idx),
value.len(),
);
}
}
pub(crate) fn alloc_manually(len: usize) -> Self {
debug_assert!(len > 0, "don't allocate an array of length 0!");
let l = array_layout::<u8>(len);
let raw = unsafe { alloc::alloc::alloc(l) };
let Some(ptr) = ptr::NonNull::new(raw) else {
alloc::alloc::handle_alloc_error(l)
};
Self { ptr }
}
pub(crate) fn as_slice_manually(&self, len: usize) -> &[u8] {
if len == 0 {
Default::default()
} else {
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), len) }
}
}
pub(crate) fn as_slice_manually_mut(&mut self, len: usize) -> &mut [u8] {
if len == 0 {
Default::default()
} else {
unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), len) }
}
}
pub(crate) fn as_string_manually(&self, len: usize) -> &str {
let bytes = self.as_slice_manually(len);
unsafe { str::from_utf8_unchecked(bytes) }
}
pub fn eq_manually(&self, other: &Self, len: usize) -> bool {
self.as_slice_manually(len) == other.as_slice_manually(len)
}
}