//! Low-level allocation and OOM-handling utilities.12mod arc;3mod boxed;4mod string;5mod try_clone;6mod try_collect;7mod try_new;8mod vec;910pub use boxed::{11BoxedSliceFromFallibleIterError, TooFewItemsOrOom, boxed_slice_write_iter,12new_boxed_slice_from_fallible_iter, new_boxed_slice_from_iter,13new_boxed_slice_from_iter_with_len, new_uninit_boxed_slice,14};15pub use string::String;16pub use try_clone::TryClone;17pub use try_collect::{TryCollect, TryExtend, TryFromIterator};18pub use try_new::{TryNew, try_new};19pub use vec::Vec;2021use crate::error::OutOfMemory;22use core::{alloc::Layout, ptr::NonNull};2324/// Try to allocate a block of memory that fits the given layout, or return an25/// `OutOfMemory` error.26///27/// # Safety28///29/// Same as `alloc::alloc::alloc`: layout must have non-zero size.30#[inline]31unsafe fn try_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {32// Safety: same as our safety conditions.33debug_assert!(layout.size() > 0);34let ptr = unsafe { std_alloc::alloc::alloc(layout) };3536if let Some(ptr) = NonNull::new(ptr) {37Ok(ptr)38} else {39Err(OutOfMemory::new(layout.size()))40}41}4243/// Tries to reallocate a block of memory, returning `OutOfMemory` on failure.44///45/// Analogue of [`alloc::alloc::realloc`].46///47/// # Safety48///49/// Same as `alloc::alloc::realloc`: `ptr` must be allocated with `layout`,50/// `layout` must be nonzero in size, and `new_size` must be nonzero and valid.51#[inline]52unsafe fn try_realloc(53ptr: *mut u8,54layout: Layout,55new_size: usize,56) -> Result<NonNull<u8>, OutOfMemory> {57// Safety: same as our safety conditions.58debug_assert!(layout.size() > 0);59debug_assert!(new_size > 0);60let ptr = unsafe { std_alloc::alloc::realloc(ptr, layout, new_size) };6162if let Some(ptr) = NonNull::new(ptr) {63Ok(ptr)64} else {65Err(OutOfMemory::new(new_size))66}67}6869/// An extension trait for ignoring `OutOfMemory` errors.70///71/// Use this to unwrap a `Result<T, OutOfMemory>` into its inner `T` or72/// otherwise panic, leveraging the type system to be sure that you aren't ever73/// accidentally unwrapping non-`OutOfMemory` errors.74pub trait PanicOnOom {75/// The non-`OutOfMemory` result of calling `panic_on_oom`.76type Result;7778/// Panic on `OutOfMemory` errors, returning the non-`OutOfMemory` result.79fn panic_on_oom(self) -> Self::Result;80}8182impl<T> PanicOnOom for Result<T, OutOfMemory> {83type Result = T;8485#[track_caller]86fn panic_on_oom(self) -> Self::Result {87match self {88Ok(x) => x,89Err(oom) => panic!("unhandled out-of-memory error: {oom}"),90}91}92}9394/// Create a `*mut str` from a pointer and length pair.95///96/// NB: This function is safe, but dereferencing it or otherwise using the97/// resulting `str` pointer's contents is unsafe and requires that the pointer98/// be valid for accessing and points to a valid utf8 sequence of `len` bytes.99fn str_ptr_from_raw_parts(ptr: *mut u8, len: usize) -> *mut str {100let ptr: *mut [u8] = core::ptr::slice_from_raw_parts_mut(ptr, len);101str_ptr_from_slice_ptr(ptr)102}103104/// Create a `*mut str` from a slice pointer.105///106/// NB: This function is safe, but dereferencing it or otherwise using the107/// resulting `str` pointer's contents is unsafe and requires that the pointer108/// be valid for accessing and points to a valid utf8 sequence of `len` bytes.109fn str_ptr_from_slice_ptr(ptr: *mut [u8]) -> *mut str {110// SAFETY: `str` is a newtype of `[u8]`.111let ptr: *mut str = unsafe { core::mem::transmute(ptr) };112ptr113}114115116