| // Part of the Crubit project, under the Apache License v2.0 with LLVM | |
| // Exceptions. See /LICENSE for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // #![feature(allocator_api)] | |
| use crate::crubit_cc_std_internal::std_allocator::{cpp_delete, cpp_new}; | |
| use core::alloc::AllocError; | |
| use core::alloc::Allocator; | |
| use core::alloc::GlobalAlloc; | |
| use core::alloc::Layout; | |
| use core::ffi::c_void; | |
| use core::ptr::NonNull; | |
| pub struct StdAllocator {} | |
| unsafe impl Allocator for StdAllocator { | |
| fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { | |
| // SAFETY: StdAllocator allows for zero-sized allocations. | |
| let raw_ptr = unsafe { self.alloc(layout) }; | |
| let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?; | |
| Ok(NonNull::slice_from_raw_parts(ptr, layout.size())) | |
| } | |
| unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { | |
| // SAFETY: Allocator and Dealloc have identical preconditions. | |
| unsafe { | |
| self.dealloc(ptr.as_ptr(), layout); | |
| } | |
| } | |
| // NOTE: Also change the GlobalAlloc impl if you add grow/etc. | |
| } | |
| /// StdAllocator is a global allocator which also accepts zero-sized allocations. | |
| /// | |
| /// This allows allocations (even of size 0) in Rust to be mixed with deallocations in C++. | |
| /// (Though, since `Global` will not pass through 0-sized allocations, this is currently of | |
| /// limited use.) | |
| unsafe impl GlobalAlloc for StdAllocator { | |
| unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | |
| cpp_new(layout.size(), layout.align()) as *mut u8 | |
| } | |
| unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { | |
| unsafe { | |
| cpp_delete(ptr as *mut c_void, layout.size(), layout.align()); | |
| } | |
| } | |
| } | |
| impl Clone for StdAllocator { | |
| fn clone(&self) -> Self { | |
| Self {} | |
| } | |
| } |