1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//!Smart pointers for Rust
//!
//!## Features
//!
//!- `alloc` Enables usage of `alloc` crate

#![no_std]
#![warn(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]

#[cfg(feature = "alloc")]
extern crate alloc;

///Describes how to de-allocate pointer.
pub trait Deleter {
    ///This function is called on `Drop`
    fn delete<T>(&mut self, ptr: *mut u8);
}

impl Deleter for () {
    #[inline(always)]
    fn delete<T>(&mut self, _: *mut u8) {}
}

impl Deleter for unsafe extern "C" fn(*mut u8) {
    #[inline(always)]
    fn delete<T>(&mut self, ptr: *mut u8) {
        unsafe {
            (*self)(ptr)
        }
    }
}

impl Deleter for unsafe fn(*mut u8) {
    #[inline(always)]
    fn delete<T>(&mut self, ptr: *mut u8) {
        unsafe {
            (*self)(ptr)
        }
    }
}

impl<F: FnMut(*mut u8)> Deleter for F {
    #[inline(always)]
    fn delete<T>(&mut self, ptr: *mut u8) {
        (*self)(ptr)
    }
}

#[cfg(feature = "alloc")]
///Default Rust deleter.
///
///Invokes destructor and de-allocates memory using global allocator, using Box.
///
///It can be useful when one would want to allow type erasure,
///but it is UB to specify invalid `T`
///
///```rust
///use smart_ptr::Unique;
///
///let var = Box::new("test".to_string());
///unsafe {
///    smart_ptr::boxed_deleter::<String>(Box::leak(var) as *mut String as *mut u8);
///}
///```
///
///## Warning
///
///Remember that things can get complicated when you cast from fat ptrs(with vtable)
pub unsafe fn boxed_deleter<T>(ptr: *mut u8) {
    debug_assert!(!ptr.is_null());

    alloc::boxed::Box::from_raw(ptr as *mut T);
}

#[derive(Default)]
///Deleter which uses global allocator via `Box`.
///
///It uses type information, provided as type parameter of `Deleter::delete` to re-create `Box` and
///destruct it
///
///Therefore user must guarantee that pointer was created with the same type information
pub struct DefaultDeleter;

#[cfg(feature = "alloc")]
impl Deleter for DefaultDeleter {
    #[inline]
    fn delete<T>(&mut self, ptr: *mut u8) {
        unsafe {
            boxed_deleter::<T>(ptr)
        }
    }
}

pub mod unique;
pub use unique::Unique;