musli_core/alloc/
alloc.rs

1use super::AllocError;
2
3/// A value allocated through [`Allocator::alloc`].
4///
5/// [`Allocator::alloc`]: super::Allocator::alloc
6///
7/// ## Examples
8///
9/// ```
10/// use musli::alloc::{AllocError, Allocator, Alloc};
11///
12/// musli::alloc::default(|alloc| {
13///     let mut buf = alloc.alloc(10u32)?;
14///
15///     unsafe {
16///         buf.as_mut_ptr().write(20u32);
17///         assert_eq!(buf.as_ptr().read(), 20u32);
18///     }
19///
20///     Ok::<_, AllocError>(())
21/// });
22/// # Ok::<_, AllocError>(())
23/// ```
24///
25/// Example of a correctly managed slice allocation:
26///
27/// ```
28/// use core::slice;
29/// use musli::alloc::{Alloc, AllocError, Allocator};
30///
31/// let values: [u32; 4] = [1, 2, 3, 4];
32///
33/// musli::alloc::default(|alloc| {
34///     let mut buf = alloc.alloc_empty::<u32>();
35///     let mut len = 0;
36///
37///     for value in values {
38///         buf.resize(len, 1)?;
39///
40///         // SAFETY: We've just resized the above buffer.
41///         unsafe {
42///             buf.as_mut_ptr().add(len).write(value);
43///         }
44///
45///         len += 1;
46///     }
47///
48///     // SAFETY: Slice does not outlive the buffer it references.
49///     let bytes = unsafe { slice::from_raw_parts(buf.as_ptr(), len) };
50///     assert_eq!(bytes, values);
51///     Ok::<_, AllocError>(())
52/// });
53/// # Ok::<_, AllocError>(())
54/// ```
55pub trait Alloc<T>: Sized {
56    /// Get a pointer into the allocation.
57    ///
58    /// ## Examples
59    ///
60    /// ```
61    /// use musli::alloc::{AllocError, Allocator, Alloc};
62    ///
63    /// musli::alloc::default(|alloc| {
64    ///     let mut buf = alloc.alloc(10u32)?;
65    ///
66    ///     unsafe {
67    ///         buf.as_mut_ptr().write(20u32);
68    ///         assert_eq!(buf.as_ptr().read(), 20u32);
69    ///     }
70    ///
71    ///     Ok::<_, AllocError>(())
72    /// });
73    /// # Ok::<_, AllocError>(())
74    /// ```
75    fn as_ptr(&self) -> *const T;
76
77    /// Get a mutable pointer into the allocation.
78    ///
79    /// ## Examples
80    ///
81    /// ```
82    /// use musli::alloc::{AllocError, Allocator, Alloc};
83    ///
84    /// musli::alloc::default(|alloc| {
85    ///     let mut buf = alloc.alloc(10u32)?;
86    ///
87    ///     unsafe {
88    ///         buf.as_mut_ptr().write(20u32);
89    ///         assert_eq!(buf.as_ptr().read(), 20u32);
90    ///     }
91    ///
92    ///     Ok::<_, AllocError>(())
93    /// });
94    /// # Ok::<_, AllocError>(())
95    /// ```
96    fn as_mut_ptr(&mut self) -> *mut T;
97
98    /// Returns the capacity of the buffer.
99    fn capacity(&self) -> usize;
100
101    /// Resize the buffer to fit at least additional elements.
102    ///
103    /// Returns the new capacity of the buffer.
104    fn resize(&mut self, len: usize, additional: usize) -> Result<(), AllocError>;
105
106    /// Try to merge one buffer with another.
107    ///
108    /// The two length parameters refers to the initialized length of the two
109    /// buffers.
110    ///
111    /// If this returns `Err(B)` if merging was not possible.
112    ///
113    /// Returns the capacity of the newly merged buffer.
114    fn try_merge<B>(&mut self, this_len: usize, other: B, other_len: usize) -> Result<(), B>
115    where
116        B: Alloc<T>;
117}