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}