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