musli_core/alloc/
allocator.rs

1use core::ptr::NonNull;
2
3use super::{Alloc, AllocError};
4
5/// The trait governing a global allocator.
6///
7/// # Safety
8///
9/// Implementing this trait promises that the implementing allocator ultimately
10/// is backed by the global allocator [`Global`] and subsequently is what will
11/// be used to allocate and free data.
12///
13/// [`Global`]: rust_alloc::alloc::Global
14pub unsafe trait GlobalAllocator
15where
16    Self: Allocator,
17{
18    /// Do not implement this trait. It is internal to Musli and will change.
19    fn __do_not_implement();
20
21    /// Construct a new instance of the global allocator.
22    #[doc(hidden)]
23    fn new() -> Self;
24
25    /// Clone an allocation.
26    fn clone_alloc<T>(alloc: &Self::Alloc<T>) -> Self::Alloc<T>;
27
28    /// Construct an allocation from the given raw parts assuming they are
29    /// allocated using the [`Global`] allocator.
30    ///
31    /// [`Global`]: std::alloc::Global
32    #[doc(hidden)]
33    fn slice_from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self::Alloc<T>;
34}
35
36/// An allocator that can be used in combination with a context.
37///
38/// # Safety
39///
40/// Setting `IS_GLOBAL` to `true` has safety implications, since it determines
41/// whether the allocation can be safely converted into a standard container or
42/// not.
43pub unsafe trait Allocator
44where
45    Self: Copy,
46{
47    /// Do not implement this trait. It is internal to Musli and will change.
48    fn __do_not_implement();
49
50    /// Whether the allocations returned by this allocatore is backed by the
51    /// global allocator or not.
52    ///
53    /// # Safety
54    ///
55    /// Setting this to `true` has safety implications, since it determines
56    /// whether the allocation can be safely converted into a standard container
57    /// or not.
58    #[doc(hidden)]
59    const IS_GLOBAL: bool;
60
61    /// A raw allocation from the allocator.
62    #[doc(hidden)]
63    type Alloc<T>: Alloc<T>;
64
65    /// Construct an empty uninitialized raw vector with an alignment matching
66    /// that of `T` that is associated with this allocator.
67    ///
68    /// ## Examples
69    ///
70    /// ```
71    /// use core::slice;
72    /// use musli::alloc::{Alloc, AllocError, Allocator};
73    ///
74    /// let values: [u32; 4] = [1, 2, 3, 4];
75    ///
76    /// musli::alloc::default(|alloc| {
77    ///     let mut buf = alloc.alloc_empty::<u32>();
78    ///     let mut len = 0;
79    ///
80    ///     for value in values {
81    ///         buf.resize(len, 1)?;
82    ///
83    ///         // SAFETY: We've just resized the above buffer.
84    ///         unsafe {
85    ///             buf.as_mut_ptr().add(len).write(value);
86    ///         }
87    ///
88    ///         len += 1;
89    ///     }
90    ///
91    ///     // SAFETY: Slice does not outlive the buffer it references.
92    ///     let bytes = unsafe { slice::from_raw_parts(buf.as_ptr(), len) };
93    ///     assert_eq!(bytes, values);
94    ///     Ok::<_, AllocError>(())
95    /// });
96    /// # Ok::<_, AllocError>(())
97    /// ```
98    #[doc(hidden)]
99    fn alloc_empty<T>(self) -> Self::Alloc<T>;
100
101    /// Construct an empty uninitialized raw allocation with an alignment
102    /// matching that of `T` that is associated with this allocator.
103    ///
104    /// ## Examples
105    ///
106    /// ```
107    /// use musli::alloc::{AllocError, Allocator, Alloc};
108    ///
109    /// musli::alloc::default(|alloc| {
110    ///     let mut buf = alloc.alloc(10u32)?;
111    ///
112    ///     unsafe {
113    ///         buf.as_mut_ptr().write(20u32);
114    ///         assert_eq!(buf.as_ptr().read(), 20u32);
115    ///     }
116    ///
117    ///     Ok::<_, AllocError>(())
118    /// });
119    /// # Ok::<_, AllocError>(())
120    /// ```
121    #[doc(hidden)]
122    fn alloc<T>(self, value: T) -> Result<Self::Alloc<T>, AllocError>;
123}