use super::*;
use alloc::alloc::{alloc, dealloc, realloc};
use core::{alloc::Layout, hint, ptr, ptr::NonNull};
#[cfg(not(loom))]
use core::sync::atomic::AtomicUsize;
#[cfg(loom)]
use loom::sync::atomic::AtomicUsize;
use internal::*;
#[inline(always)]
pub(crate) fn amortized_growth(cur_len: usize, additional: usize) -> usize {
let required = cur_len.saturating_add(additional);
let amortized = cur_len.saturating_mul(3) / 2;
amortized.max(required)
}
#[repr(C)]
pub(super) struct HeapBuffer {
ptr: NonNull<u8>,
len: TextLen,
}
struct ExactHeader {
count: AtomicUsize,
}
struct Header {
capacity: Capacity,
count: AtomicUsize,
}
const _: () = {
assert!(size_of::<HeapBuffer>() == MAX_INLINE_SIZE);
assert!(align_of::<HeapBuffer>() == align_of::<usize>());
};
impl HeapBuffer {
pub(super) fn new(text: &str) -> Result<Self, ReserveError> {
HeapBuffer::with_exact_capacity(text, text.len())
}
pub(super) fn new_exact(text: &str) -> Result<Self, ReserveError> {
let text_len = text.len();
let len = TextLen::new_exact(text_len)?;
let ptr = HeapBuffer::allocate_exact_ptr(text_len)?;
if len.is_heap() {
unsafe {
let len_ptr = ptr.sub(HeapBuffer::exact_header_offset()).sub(size_of::<usize>());
ptr::write(len_ptr.as_ptr().cast(), text_len);
}
}
unsafe { ptr::copy_nonoverlapping(text.as_ptr(), ptr.as_ptr(), text_len) };
Ok(HeapBuffer { ptr, len })
}
pub(super) fn new_exact_joined_slices<T: AsRef<str>>(
slices: &[T],
separator: &str,
text_len: usize,
) -> Result<Self, ReserveError> {
let len = TextLen::new_exact(text_len)?;
let ptr = HeapBuffer::allocate_exact_ptr(text_len)?;
if len.is_heap() {
unsafe {
let len_ptr = ptr.sub(HeapBuffer::exact_header_offset()).sub(size_of::<usize>());
ptr::write(len_ptr.as_ptr().cast(), text_len);
}
}
let mut guard = ExactBufferGuard(Some(HeapBuffer { ptr, len }));
let mut offset = 0;
for (index, text) in slices.iter().enumerate() {
if index > 0 {
HeapBuffer::copy_exact_part(ptr, separator, &mut offset, text_len)?;
}
HeapBuffer::copy_exact_part(ptr, text.as_ref(), &mut offset, text_len)?;
}
if offset != text_len {
return Err(ReserveError);
}
Ok(guard.0.take().unwrap())
}
fn copy_exact_part(
ptr: NonNull<u8>,
text: &str,
offset: &mut usize,
text_len: usize,
) -> Result<(), ReserveError> {
let end = offset.checked_add(text.len()).ok_or(ReserveError)?;
if end > text_len {
return Err(ReserveError);
}
unsafe {
ptr::copy_nonoverlapping(text.as_ptr(), ptr.add(*offset).as_ptr(), text.len());
}
*offset = end;
Ok(())
}
pub(crate) fn with_capacity(capacity: usize) -> Result<Self, ReserveError> {
let len = TextLen::new_growable(0)?;
let cap = Capacity::new(capacity)?;
let ptr = HeapBuffer::allocate_growable_ptr(cap)?;
Ok(HeapBuffer { ptr, len })
}
pub(super) fn with_exact_capacity(text: &str, capacity: usize) -> Result<Self, ReserveError> {
if text.len() > capacity {
return Err(ReserveError);
}
let mut buffer = HeapBuffer::with_capacity(capacity)?;
unsafe {
ptr::copy_nonoverlapping(text.as_ptr(), buffer.ptr.as_ptr(), text.len());
buffer.set_len(text.len());
}
Ok(buffer)
}
#[cold]
#[inline(never)]
pub(super) fn with_additional(text: &str, additional: usize) -> Result<Self, ReserveError> {
let text_len = text.len();
let len = TextLen::new_growable(text_len)?;
let ptr = {
let new_capacity = Capacity::new(amortized_growth(text_len, additional))?;
HeapBuffer::allocate_growable_ptr(new_capacity)?
};
if len.is_heap() {
unsafe {
let len_ptr = ptr.sub(HeapBuffer::growable_header_offset()).sub(size_of::<usize>());
ptr::write(len_ptr.as_ptr().cast(), text_len);
}
}
unsafe { ptr::copy_nonoverlapping(text.as_ptr(), ptr.as_ptr(), text_len) };
Ok(HeapBuffer { ptr, len })
}
pub(super) fn capacity(&self) -> usize {
if self.is_exact() { self.len() } else { self.header().capacity.as_usize() }
}
pub(super) const fn is_exact(&self) -> bool {
self.len.is_exact()
}
#[cfg(feature = "get-size")]
pub(super) fn allocation_size(&self) -> usize {
self.header_offset()
+ self.capacity()
+ usize::from(self.has_heap_len_layout()) * size_of::<usize>()
}
pub(crate) fn ptr(&self) -> NonNull<u8> {
self.ptr
}
pub(super) const fn len(&self) -> usize {
if self.len.is_heap() {
unsafe {
let len_ptr = self.ptr.sub(self.header_offset()).sub(size_of::<usize>());
ptr::read(len_ptr.as_ptr().cast())
}
} else {
self.len.as_usize()
}
}
pub(super) fn as_str(&self) -> &str {
let len = self.len();
let ptr = self.ptr.as_ptr();
unsafe { core::str::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) }
}
pub(super) unsafe fn realloc(&mut self, new_capacity: usize) -> Result<(), ReserveError> {
debug_assert!(!self.is_exact());
debug_assert!(self.is_unique());
debug_assert!(self.len() <= new_capacity);
let new_capacity = Capacity::new(new_capacity)?;
let cur_capacity = self.header().capacity;
let cur_layout = match HeapBuffer::layout_from_capacity(cur_capacity) {
Ok(layout) => layout,
Err(_) => {
if cfg!(debug_assertions) {
panic!("invalid layout, unexpected `capacity` modification may have occurred");
}
unsafe { hint::unreachable_unchecked() }
}
};
let len_heap = match (is_len_heap_layout(cur_capacity), is_len_heap_layout(new_capacity)) {
(false, false) => false,
(true, true) => true,
(true, false) | (false, true) => {
let str = self.as_str();
let mut new_buf = HeapBuffer::with_capacity(new_capacity.as_usize())?;
unsafe {
ptr::copy_nonoverlapping(str.as_ptr(), new_buf.ptr.as_ptr(), str.len());
new_buf.set_len(str.len());
self.dealloc();
}
*self = new_buf;
return Ok(());
}
};
let new_alloc_size = {
#[cfg(target_pointer_width = "64")]
{
size_of::<Header>().wrapping_add(new_capacity.as_usize())
}
#[cfg(target_pointer_width = "32")]
{
const ALLOC_LIMIT: usize = (isize::MAX as usize + 1) - HeapBuffer::align();
let mut alloc_size = size_of::<Header>().saturating_add(new_capacity.as_usize());
if len_heap {
alloc_size = alloc_size.saturating_add(size_of::<usize>());
}
if alloc_size > ALLOC_LIMIT {
return Err(ReserveError);
}
alloc_size
}
};
let mut allocation = unsafe { realloc(self.allocation(), cur_layout, new_alloc_size) };
if allocation.is_null() {
return Err(ReserveError);
}
if len_heap {
unsafe { allocation = allocation.add(size_of::<usize>()) };
}
unsafe {
ptr::write(
allocation.cast(),
Header {
capacity: new_capacity,
count: AtomicUsize::new(1), },
);
let ptr = allocation.add(HeapBuffer::growable_header_offset());
self.ptr = NonNull::new_unchecked(ptr);
}
Ok(())
}
pub(super) unsafe fn realloc_into_exact(&mut self) -> Result<(), ReserveError> {
debug_assert!(!self.is_exact());
debug_assert!(self.is_unique());
let len = self.len();
let old_capacity = self.header().capacity;
let new_capacity = Capacity::new(len)?;
let new_len = TextLen::new_exact(len)?;
let old_layout = HeapBuffer::layout_from_capacity(old_capacity)?;
let new_layout = HeapBuffer::layout_from_len(len)?;
let old_len_prefix = if is_len_heap_layout(old_capacity) { size_of::<usize>() } else { 0 };
let new_len_prefix = if is_len_heap_layout(new_capacity) { size_of::<usize>() } else { 0 };
let allocation = unsafe { self.allocation() };
let old_data =
unsafe { allocation.add(old_len_prefix + HeapBuffer::growable_header_offset()) };
let new_data =
unsafe { allocation.add(new_len_prefix + HeapBuffer::exact_header_offset()) };
unsafe { ptr::copy(old_data, new_data, len) };
let new_allocation = unsafe { realloc(allocation, old_layout, new_layout.size()) };
if new_allocation.is_null() {
unsafe {
ptr::copy(new_data, old_data, len);
if old_len_prefix != 0 {
ptr::write(allocation.cast(), len);
}
let header = allocation.add(old_len_prefix).cast::<Header>();
ptr::write(header, Header { capacity: old_capacity, count: AtomicUsize::new(1) });
}
return Err(ReserveError);
}
unsafe {
if new_len_prefix != 0 {
ptr::write(new_allocation.cast(), len);
}
let header = new_allocation.add(new_len_prefix).cast::<ExactHeader>();
ptr::write(header, ExactHeader { count: AtomicUsize::new(1) });
let data = new_allocation.add(new_len_prefix + HeapBuffer::exact_header_offset());
self.ptr = NonNull::new_unchecked(data);
}
self.len = new_len;
Ok(())
}
pub(super) unsafe fn realloc_into_growable(&mut self) -> Result<(), ReserveError> {
debug_assert!(self.is_exact());
debug_assert!(self.is_unique());
let len = self.len();
let capacity = Capacity::new(len)?;
let new_len = TextLen::new_growable(len)?;
let old_layout = HeapBuffer::layout_from_len(len)?;
let new_layout = HeapBuffer::layout_from_capacity(capacity)?;
let len_prefix = if is_len_heap_layout(capacity) { size_of::<usize>() } else { 0 };
let allocation = unsafe { self.allocation() };
let new_allocation = unsafe { realloc(allocation, old_layout, new_layout.size()) };
if new_allocation.is_null() {
return Err(ReserveError);
}
unsafe {
let old_data = new_allocation.add(len_prefix + HeapBuffer::exact_header_offset());
let new_data = new_allocation.add(len_prefix + HeapBuffer::growable_header_offset());
ptr::copy(old_data, new_data, len);
if len_prefix != 0 {
ptr::write(new_allocation.cast(), len);
}
let header = new_allocation.add(len_prefix).cast::<Header>();
ptr::write(header, Header { capacity, count: AtomicUsize::new(1) });
self.ptr = NonNull::new_unchecked(new_data);
}
self.len = new_len;
Ok(())
}
#[inline]
pub(super) unsafe fn release(&mut self) {
if self.reference_count().fetch_sub(1, Release) == 1 {
unsafe { self.dealloc_last_reference() };
}
}
#[cold]
#[inline(never)]
unsafe fn dealloc_last_reference(&mut self) {
fence(Acquire);
unsafe { self.dealloc() };
}
unsafe fn dealloc(&mut self) {
let layout = match if self.is_exact() {
HeapBuffer::layout_from_len(self.len())
} else {
HeapBuffer::layout_from_capacity(self.header().capacity)
} {
Ok(layout) => layout,
Err(_) => {
if cfg!(debug_assertions) {
panic!("invalid layout, unexpected `capacity` modification may have occurred");
}
unsafe { hint::unreachable_unchecked() }
}
};
unsafe {
dealloc(self.allocation(), layout);
}
}
#[inline(always)]
pub(super) fn is_unique(&self) -> bool {
self.reference_count().load(Acquire) == 1
}
pub(super) fn is_len_on_heap(&self) -> bool {
self.len.is_heap()
}
pub(super) fn reference_count(&self) -> &AtomicUsize {
if self.is_exact() { &self.exact_header().count } else { &self.header().count }
}
pub(super) unsafe fn set_len(&mut self, len: usize) {
debug_assert!(!self.is_exact());
debug_assert!(len <= self.capacity());
let new_len = match TextLen::new_growable(len) {
Ok(len) => len,
Err(_) => {
if cfg!(debug_assertions) {
panic!("Invalid `set_len` call");
}
unsafe { hint::unreachable_unchecked() }
}
};
debug_assert!(if new_len.is_heap() { self.is_unique() } else { true });
self.len = new_len;
#[cold]
fn write_len_on_heap(ptr: NonNull<u8>, len: usize) {
unsafe {
let len_ptr = ptr.sub(HeapBuffer::growable_header_offset()).sub(size_of::<usize>());
ptr::write(len_ptr.as_ptr().cast(), len);
}
}
if self.len.is_heap() {
write_len_on_heap(self.ptr, len);
}
}
fn allocate_exact_ptr(len: usize) -> Result<NonNull<u8>, ReserveError> {
let layout = HeapBuffer::layout_from_len(len)?;
let mut allocation = unsafe { alloc(layout) };
if allocation.is_null() {
return Err(ReserveError);
}
if is_len_heap_layout(Capacity::new(len)?) {
unsafe { allocation = allocation.add(size_of::<usize>()) };
}
unsafe {
ptr::write(allocation.cast(), ExactHeader { count: AtomicUsize::new(1) });
let ptr = allocation.add(HeapBuffer::exact_header_offset());
Ok(NonNull::new_unchecked(ptr))
}
}
fn allocate_growable_ptr(capacity: Capacity) -> Result<NonNull<u8>, ReserveError> {
let layout = HeapBuffer::layout_from_capacity(capacity)?;
let mut allocation = unsafe { alloc(layout) };
if allocation.is_null() {
return Err(ReserveError);
}
if is_len_heap_layout(capacity) {
unsafe { allocation = allocation.add(size_of::<usize>()) };
}
unsafe {
ptr::write(allocation.cast(), Header { capacity, count: AtomicUsize::new(1) });
let ptr = allocation.add(HeapBuffer::growable_header_offset());
Ok(NonNull::new_unchecked(ptr))
}
}
fn layout_from_len(len: usize) -> Result<Layout, ReserveError> {
let capacity = Capacity::new(len)?;
HeapBuffer::layout(HeapBuffer::exact_header_offset(), capacity)
}
fn layout_from_capacity(capacity: Capacity) -> Result<Layout, ReserveError> {
HeapBuffer::layout(HeapBuffer::growable_header_offset(), capacity)
}
fn layout(header_size: usize, capacity: Capacity) -> Result<Layout, ReserveError> {
let alloc_size = header_size
.checked_add(capacity.as_usize())
.and_then(|size| {
if is_len_heap_layout(capacity) {
size.checked_add(size_of::<usize>())
} else {
Some(size)
}
})
.ok_or(ReserveError)?;
let align = HeapBuffer::align();
Layout::from_size_align(alloc_size, align).map_err(
#[cold]
|_| ReserveError,
)
}
unsafe fn allocation(&self) -> *mut u8 {
unsafe {
if self.has_heap_len_layout() {
cold_path();
self.ptr.as_ptr().cast::<u8>().sub(self.header_offset()).sub(size_of::<usize>())
} else {
self.ptr.as_ptr().cast::<u8>().sub(self.header_offset())
}
}
}
fn header(&self) -> &Header {
debug_assert!(!self.is_exact());
unsafe { &*self.ptr.as_ptr().sub(HeapBuffer::growable_header_offset()).cast() }
}
fn exact_header(&self) -> &ExactHeader {
debug_assert!(self.is_exact());
unsafe { &*self.ptr.as_ptr().sub(HeapBuffer::exact_header_offset()).cast() }
}
fn has_heap_len_layout(&self) -> bool {
if self.is_exact() {
self.len.is_heap()
} else {
is_len_heap_layout(self.header().capacity)
}
}
const fn align() -> usize {
const {
assert!(align_of::<Header>() == align_of::<usize>());
assert!(align_of::<ExactHeader>() == align_of::<usize>());
assert!(align_of::<NonNull<u8>>() == align_of::<usize>());
}
align_of::<usize>()
}
const fn exact_header_offset() -> usize {
max(size_of::<ExactHeader>(), HeapBuffer::align())
}
const fn growable_header_offset() -> usize {
max(size_of::<Header>(), HeapBuffer::align())
}
const fn header_offset(&self) -> usize {
if self.is_exact() {
HeapBuffer::exact_header_offset()
} else {
HeapBuffer::growable_header_offset()
}
}
}
struct ExactBufferGuard(Option<HeapBuffer>);
impl Drop for ExactBufferGuard {
fn drop(&mut self) {
if let Some(mut buffer) = self.0.take() {
unsafe { buffer.release() };
}
}
}
const fn max(x: usize, y: usize) -> usize {
if x > y { x } else { y }
}
mod internal {
use super::*;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(super) struct TextLen(usize);
const USIZE_SIZE: usize = size_of::<usize>();
const MAX_LEN: usize = {
let mut bytes = [255; USIZE_SIZE];
bytes[USIZE_SIZE - 1] = 0;
usize::from_le_bytes(bytes) - if cfg!(target_pointer_width = "32") { 1 } else { 0 }
};
impl TextLen {
const EXACT_TAG: usize = {
let mut bytes = [0; USIZE_SIZE];
bytes[USIZE_SIZE - 1] = LastByte::ExactHeapMarker as u8;
usize::from_ne_bytes(bytes)
};
const GROWABLE_TAG: usize = {
let mut bytes = [0; USIZE_SIZE];
bytes[USIZE_SIZE - 1] = LastByte::HeapMarker as u8;
usize::from_ne_bytes(bytes)
};
#[cfg(target_pointer_width = "32")]
const EXACT_ON_THE_HEAP: usize = {
let mut bytes = [255; USIZE_SIZE];
bytes[USIZE_SIZE - 1] = LastByte::ExactHeapMarker as u8;
usize::from_ne_bytes(bytes)
};
#[cfg(target_pointer_width = "32")]
const GROWABLE_ON_THE_HEAP: usize = {
let mut bytes = [255; USIZE_SIZE];
bytes[USIZE_SIZE - 1] = LastByte::HeapMarker as u8;
usize::from_ne_bytes(bytes)
};
pub(super) const fn new_exact(size: usize) -> Result<Self, ReserveError> {
Self::new(size, Self::EXACT_TAG)
}
pub(super) const fn new_growable(size: usize) -> Result<Self, ReserveError> {
Self::new(size, Self::GROWABLE_TAG)
}
const fn new(size: usize, tag: usize) -> Result<Self, ReserveError> {
if size > MAX_LEN {
#[cfg(target_pointer_width = "64")]
return Err(ReserveError);
#[cfg(target_pointer_width = "32")]
return Ok(TextLen(if tag == Self::EXACT_TAG {
Self::EXACT_ON_THE_HEAP
} else {
Self::GROWABLE_ON_THE_HEAP
}));
}
Ok(TextLen(size.to_le() | tag))
}
pub(super) const fn is_exact(&self) -> bool {
self.tag() == Self::EXACT_TAG
}
#[inline(always)]
pub(super) const fn is_heap(&self) -> bool {
#[cfg(target_pointer_width = "64")]
return false;
#[cfg(target_pointer_width = "32")]
return self.0
== if self.is_exact() {
Self::EXACT_ON_THE_HEAP
} else {
Self::GROWABLE_ON_THE_HEAP
};
}
pub(super) const fn as_usize(self) -> usize {
let size = self.0 ^ self.tag();
let bytes = size.to_ne_bytes();
usize::from_le_bytes(bytes)
}
const fn tag(&self) -> usize {
let mut bytes = [0; USIZE_SIZE];
bytes[USIZE_SIZE - 1] = self.0.to_ne_bytes()[USIZE_SIZE - 1];
usize::from_ne_bytes(bytes)
}
}
#[cfg_attr(target_pointer_width = "64", allow(unused_variables))]
#[inline(always)]
pub(super) fn is_len_heap_layout(capacity: Capacity) -> bool {
#[cfg(target_pointer_width = "64")]
return false;
#[cfg(target_pointer_width = "32")]
return capacity.as_usize() > MAX_LEN;
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(super) struct Capacity(usize);
impl Capacity {
pub(crate) fn new(capacity: usize) -> Result<Self, ReserveError> {
#[cfg(target_pointer_width = "64")]
if capacity > MAX_LEN {
cold_path();
return Err(ReserveError);
}
Ok(Capacity(capacity))
}
pub(crate) fn as_usize(&self) -> usize {
self.0
}
}
#[cold]
pub(super) fn cold_path() {}
#[cfg(all(test, target_pointer_width = "32"))]
mod tests {
use super::*;
#[test]
fn heap_stored_length_preserves_repr_tag() {
let exact = TextLen::new_exact(MAX_LEN + 1).unwrap();
let growable = TextLen::new_growable(MAX_LEN + 1).unwrap();
assert!(exact.is_heap());
assert!(exact.is_exact());
assert_eq!(exact.0.to_ne_bytes()[USIZE_SIZE - 1], LastByte::ExactHeapMarker as u8);
assert!(growable.is_heap());
assert!(!growable.is_exact());
assert_eq!(growable.0.to_ne_bytes()[USIZE_SIZE - 1], LastByte::HeapMarker as u8);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn exact_layout_omits_capacity() {
assert_eq!(HeapBuffer::exact_header_offset(), size_of::<AtomicUsize>());
assert_eq!(HeapBuffer::growable_header_offset(), 2 * size_of::<usize>());
let len = MAX_INLINE_SIZE + 1;
assert_eq!(
HeapBuffer::layout_from_len(len).unwrap().size(),
size_of::<AtomicUsize>() + len
);
assert_eq!(
HeapBuffer::layout_from_capacity(Capacity::new(len).unwrap()).unwrap().size(),
2 * size_of::<usize>() + len
);
}
#[test]
fn constructors_select_expected_layout() {
let text = "a string longer than the inline limit";
let mut exact = HeapBuffer::new_exact(text).unwrap();
let mut exact_joined = HeapBuffer::new_exact_joined_slices(
&["a string", "longer than", "the inline limit"],
" ",
text.len(),
)
.unwrap();
let mut growable = HeapBuffer::new(text).unwrap();
assert!(exact.is_exact());
assert!(exact_joined.is_exact());
assert!(!growable.is_exact());
assert_eq!(exact.capacity(), text.len());
assert_eq!(exact_joined.as_str(), text);
assert_eq!(exact_joined.capacity(), text.len());
assert_eq!(growable.capacity(), text.len());
unsafe {
exact.release();
exact_joined.release();
growable.release();
}
}
#[cfg(target_pointer_width = "32")]
#[test]
fn growable_layout_rejects_capacity_past_32_bit_limit() {
const MAX_CAPACITY: usize = (1 << 31) - 16;
assert_eq!(MAX_CAPACITY, 2_147_483_632);
assert!(HeapBuffer::layout_from_capacity(Capacity::new(MAX_CAPACITY).unwrap()).is_ok());
assert!(
HeapBuffer::layout_from_capacity(Capacity::new(MAX_CAPACITY + 1).unwrap()).is_err()
);
}
#[test]
fn realloc_between_exact_and_growable_layouts() {
let text = "short multibyte text: é日";
let mut buffer = HeapBuffer::with_exact_capacity(text, 128).unwrap();
assert!(!buffer.is_exact());
assert_eq!(buffer.capacity(), 128);
unsafe { buffer.realloc_into_exact().unwrap() };
assert!(buffer.is_exact());
assert_eq!(buffer.as_str(), text);
assert_eq!(buffer.capacity(), text.len());
unsafe { buffer.realloc_into_growable().unwrap() };
assert!(!buffer.is_exact());
assert_eq!(buffer.as_str(), text);
assert_eq!(buffer.capacity(), text.len());
unsafe { buffer.release() };
}
#[cfg(target_pointer_width = "32")]
#[test]
fn realloc_into_exact_removes_heap_length_prefix() {
let mut buffer = HeapBuffer::with_exact_capacity("short", 1 << 24).unwrap();
assert!(buffer.has_heap_len_layout());
unsafe { buffer.realloc_into_exact().unwrap() };
assert!(buffer.is_exact());
assert!(!buffer.has_heap_len_layout());
assert_eq!(buffer.as_str(), "short");
unsafe { buffer.release() };
}
#[cfg(target_pointer_width = "32")]
#[test]
fn realloc_growable_across_heap_length_prefix() {
const INLINE_LENGTH_LIMIT: usize = (1 << 24) - 2;
const PREFIXED_CAPACITY: usize = 1 << 24;
let mut buffer = HeapBuffer::with_exact_capacity("short", INLINE_LENGTH_LIMIT).unwrap();
assert!(!buffer.has_heap_len_layout());
unsafe { buffer.realloc(PREFIXED_CAPACITY).unwrap() };
assert!(buffer.has_heap_len_layout());
assert_eq!(buffer.as_str(), "short");
assert_eq!(buffer.capacity(), PREFIXED_CAPACITY);
unsafe { buffer.realloc(INLINE_LENGTH_LIMIT).unwrap() };
assert!(!buffer.has_heap_len_layout());
assert_eq!(buffer.as_str(), "short");
assert_eq!(buffer.capacity(), INLINE_LENGTH_LIMIT);
unsafe { buffer.release() };
}
#[cfg(target_pointer_width = "32")]
#[test]
fn realloc_between_prefixed_exact_and_growable_layouts() {
let text = "a".repeat(1 << 24);
let mut buffer = HeapBuffer::new_exact(&text).unwrap();
assert!(buffer.is_exact());
assert!(buffer.has_heap_len_layout());
unsafe { buffer.realloc_into_growable().unwrap() };
assert!(!buffer.is_exact());
assert!(buffer.has_heap_len_layout());
assert_eq!(buffer.as_str(), text);
unsafe { buffer.realloc_into_exact().unwrap() };
assert!(buffer.is_exact());
assert!(buffer.has_heap_len_layout());
assert_eq!(buffer.as_str(), text);
unsafe { buffer.release() };
}
}