musli/alloc/mod.rs
1//! Allocation support for [Müsli].
2//!
3//! This crate contains two types of allocators:
4//! * The [`Global`] allocator, which uses the global allocation facilities.
5//! * The [`Slice`] allocator, which can allocate buffers from a fixed-size
6//! slice.
7//!
8//! The following types are also provided for convenience:
9//! * [`Vec`] which can be used as a vector of allocations.
10//! * [`String`] which can be used as a safe string container.
11//!
12//! <br>
13//!
14//! ## Examples
15//!
16//! ```
17//! use musli::alloc::{AllocError, Vec};
18//!
19//! musli::alloc::default(|alloc| {
20//! let mut a = Vec::new_in(alloc);
21//! let mut b = Vec::new_in(alloc);
22//!
23//! b.extend_from_slice(b"He11o")?;
24//! a.extend_from_slice(b.as_slice())?;
25//!
26//! assert_eq!(a.as_slice(), b"He11o");
27//! assert_eq!(a.len(), 5);
28//!
29//! a.extend_from_slice(b" W0rld")?;
30//!
31//! assert_eq!(a.as_slice(), b"He11o W0rld");
32//! assert_eq!(a.len(), 11);
33//!
34//! let mut c = Vec::new_in(alloc);
35//! c.extend_from_slice(b"!")?;
36//! a.extend_from_slice(c.as_slice())?;
37//!
38//! assert_eq!(a.as_slice(), b"He11o W0rld!");
39//! assert_eq!(a.len(), 12);
40//! Ok::<_, AllocError>(())
41//! });
42//! # Ok::<_, musli::alloc::AllocError>(())
43//! ```
44//!
45//! Explicitly using a buffer on the stack with the [`Slice`] allocator:
46//!
47//! ```
48//! use musli::alloc::{ArrayBuffer, Slice, Vec};
49//!
50//! let mut buf = ArrayBuffer::new();
51//! let alloc = Slice::new(&mut buf);
52//!
53//! let mut a = Vec::new_in(&alloc);
54//! let mut b = Vec::new_in(&alloc);
55//!
56//! b.extend_from_slice(b"He11o")?;
57//! a.extend_from_slice(b.as_slice())?;
58//!
59//! assert_eq!(a.as_slice(), b"He11o");
60//! assert_eq!(a.len(), 5);
61//!
62//! a.extend_from_slice(b" W0rld")?;
63//!
64//! assert_eq!(a.as_slice(), b"He11o W0rld");
65//! assert_eq!(a.len(), 11);
66//!
67//! let mut c = Vec::new_in(&alloc);
68//! c.extend_from_slice(b"!")?;
69//! a.extend_from_slice(c.as_slice())?;
70//!
71//! assert_eq!(a.as_slice(), b"He11o W0rld!");
72//! assert_eq!(a.len(), 12);
73//! # Ok::<_, musli::alloc::AllocError>(())
74//! ```
75//!
76//! [Müsli]: <https://docs.rs/musli>
77
78#[cfg(test)]
79mod tests;
80
81mod default;
82#[doc(inline)]
83pub use self::default::{DEFAULT_ARRAY_BUFFER, DefaultAllocator};
84
85#[doc(inline)]
86pub use musli_core::alloc::{
87 Alloc, AllocError, Allocator, Box, GlobalAllocator, String, ToOwned, Vec,
88};
89
90#[cfg(feature = "alloc")]
91mod global;
92#[cfg(feature = "alloc")]
93#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
94pub use self::global::{Global, GlobalAlloc};
95
96#[doc(hidden)]
97#[cfg(feature = "alloc")]
98#[deprecated = "`System` has been renamed to `Global`"]
99pub type System = Global;
100
101#[doc(hidden)]
102#[cfg(feature = "alloc")]
103#[deprecated = "`SystemAlloc` has been renamed to `GlobalAlloc`"]
104pub type SystemAlloc<T> = GlobalAlloc<T>;
105
106mod disabled;
107#[doc(inline)]
108pub use self::disabled::Disabled;
109
110mod slice;
111#[doc(inline)]
112pub use self::slice::{Slice, SliceAlloc};
113
114mod array_buffer;
115pub use self::array_buffer::ArrayBuffer;
116
117mod slice_buffer;
118pub use self::slice_buffer::SliceBuffer;
119
120/// Call the given block `body` with an instance of the [`DefaultAllocator`].
121///
122/// This is useful if you want to write application which are agnostic to
123/// whether the `alloc` feature is or isn't enabled.
124///
125/// * If the `alloc` feature is enabled, this is the [`Global`] allocator.
126/// * If the `alloc` feature is disabled, this is the [`Slice`] allocator with
127/// [`DEFAULT_ARRAY_BUFFER`] bytes allocated on the stack. The second
128/// parameters allows for this to be tweaked.
129///
130/// Note that the [`DEFAULT_ARRAY_BUFFER`] parameter is always present since it
131/// is necessary to make the type generic over all default allocators.
132///
133/// # Examples
134///
135/// ```
136/// use musli::alloc::{AllocError, Vec};
137///
138/// musli::alloc::default(|alloc| {
139/// let mut a = Vec::new_in(alloc);
140/// let mut b = Vec::new_in(alloc);
141///
142/// b.extend_from_slice(b"He11o")?;
143/// a.extend_from_slice(b.as_slice())?;
144///
145/// assert_eq!(a.as_slice(), b"He11o");
146/// assert_eq!(a.len(), 5);
147///
148/// a.extend_from_slice(b" W0rld")?;
149///
150/// assert_eq!(a.as_slice(), b"He11o W0rld");
151/// assert_eq!(a.len(), 11);
152///
153/// let mut c = Vec::new_in(alloc);
154/// c.extend_from_slice(b"!")?;
155/// a.extend_from_slice(c.as_slice())?;
156///
157/// assert_eq!(a.as_slice(), b"He11o W0rld!");
158/// assert_eq!(a.len(), 12);
159/// Ok::<_, AllocError>(())
160/// });
161/// # Ok::<_, musli::alloc::AllocError>(())
162/// ```
163#[inline]
164pub fn default<O>(body: impl FnOnce(&DefaultAllocator<'_, DEFAULT_ARRAY_BUFFER>) -> O) -> O {
165 default_allocator_impl::<DEFAULT_ARRAY_BUFFER, O>(body)
166}
167
168/// Same as [`default()`] but allows for specifying a default static buffer size
169/// other than [`DEFAULT_ARRAY_BUFFER`].
170///
171/// See [`default()`] for more information.
172///
173/// # Examples
174///
175/// ```
176/// use musli::alloc::{AllocError, Vec};
177///
178/// musli::alloc::with_buffer::<128, _>(|alloc| {
179/// let mut a = Vec::new_in(alloc);
180/// let mut b = Vec::new_in(alloc);
181///
182/// b.extend_from_slice(b"He11o")?;
183/// a.extend_from_slice(b.as_slice())?;
184///
185/// assert_eq!(a.as_slice(), b"He11o");
186/// assert_eq!(a.len(), 5);
187///
188/// a.extend_from_slice(b" W0rld")?;
189///
190/// assert_eq!(a.as_slice(), b"He11o W0rld");
191/// assert_eq!(a.len(), 11);
192///
193/// let mut c = Vec::new_in(alloc);
194/// c.extend_from_slice(b"!")?;
195/// a.extend_from_slice(c.as_slice())?;
196///
197/// assert_eq!(a.as_slice(), b"He11o W0rld!");
198/// assert_eq!(a.len(), 12);
199/// Ok::<_, AllocError>(())
200/// });
201/// # Ok::<_, musli::alloc::AllocError>(())
202/// ```
203#[inline]
204pub fn with_buffer<const BUF: usize, O>(body: impl FnOnce(&DefaultAllocator<'_, BUF>) -> O) -> O {
205 default_allocator_impl::<BUF, O>(body)
206}
207
208#[cfg(feature = "alloc")]
209#[inline(always)]
210fn default_allocator_impl<const BUF: usize, O>(
211 body: impl FnOnce(&DefaultAllocator<'_, BUF>) -> O,
212) -> O {
213 let alloc = DefaultAllocator::new(Global::new());
214 body(&alloc)
215}
216
217#[cfg(not(feature = "alloc"))]
218#[inline(always)]
219fn default_allocator_impl<const BUF: usize, O>(
220 body: impl FnOnce(&DefaultAllocator<'_, BUF>) -> O,
221) -> O {
222 let mut buf = crate::alloc::ArrayBuffer::<BUF>::with_size();
223 let slice = crate::alloc::Slice::new(&mut buf);
224 let alloc = DefaultAllocator::new(slice);
225 body(&alloc)
226}