blob: d317f9ba8974561328a2f36412d3d6c77ae0613c [file] [log] [blame] [edit]
// 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
use crate::crubit_cc_std_internal::std_allocator;
use core::ptr::null_mut;
/// A smart pointer that owns and manages another object of type `T` via a
/// pointer, ABI-compatible with `std::unique_ptr` using default deleter from
/// C++.
#[allow(non_snake_case)]
#[repr(C)]
pub struct unique_ptr<T: Sized> {
// Invariants:
// 1. `ptr` is either null, or allocated by C++ `new`.
// 2. If `ptr` is not null, it is owned by this `unique_ptr`.
ptr: *mut T,
}
impl<T: Sized> unique_ptr<T> {
/// Takes ownership of the provided raw pointer.
///
/// # Safety
///
/// `ptr` must either be null, or allocated by C++ `new`. Otherwise, the
/// behavior is undefined.
pub unsafe fn new(ptr: *mut T) -> Self {
Self { ptr }
}
pub fn get(&self) -> *mut T {
self.ptr
}
pub fn release(&mut self) -> *mut T {
core::mem::replace(&mut self.ptr, null_mut())
}
}
impl<T> Drop for unique_ptr<T> {
fn drop(&mut self) {
if !self.ptr.is_null() {
unsafe {
// SAFETY: a non-null `self.ptr` is a pointer to a `T` allocated with C++ `new`,
// which should be satisfied by the constructor.
core::ptr::drop_in_place(self.ptr);
std_allocator::cpp_delete(
self.ptr as _,
core::mem::size_of::<T>(),
core::mem::align_of::<T>(),
);
}
}
}
}