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::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.write(b"He11o");
25//!     a.write(b.as_slice());
26//!
27//!     assert_eq!(a.as_slice(), b"He11o");
28//!     assert_eq!(a.len(), 5);
29//!
30//!     a.write(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.write(b"!");
37//!     a.write(c.as_slice());
38//!
39//!     assert_eq!(a.as_slice(), b"He11o W0rld!");
40//!     assert_eq!(a.len(), 12);
41//! });
42//! ```
43//!
44//! Explicitly using a buffer on the stack with the [`Slice`] allocator:
45//!
46//! ```
47//! use musli::alloc::{ArrayBuffer, Slice, Vec};
48//!
49//! let mut buf = ArrayBuffer::new();
50//! let alloc = Slice::new(&mut buf);
51//!
52//! let mut a = Vec::new_in(&alloc);
53//! let mut b = Vec::new_in(&alloc);
54//!
55//! b.write(b"He11o");
56//! a.write(b.as_slice());
57//!
58//! assert_eq!(a.as_slice(), b"He11o");
59//! assert_eq!(a.len(), 5);
60//!
61//! a.write(b" W0rld");
62//!
63//! assert_eq!(a.as_slice(), b"He11o W0rld");
64//! assert_eq!(a.len(), 11);
65//!
66//! let mut c = Vec::new_in(&alloc);
67//! c.write(b"!");
68//! a.write(c.as_slice());
69//!
70//! assert_eq!(a.as_slice(), b"He11o W0rld!");
71//! assert_eq!(a.len(), 12);
72//! ```
73//!
74//! [Müsli]: <https://docs.rs/musli>
75//! [`std::alloc::System`]: https://doc.rust-lang.org/std/alloc/struct.System.html
76
77#[cfg(test)]
78mod tests;
79
80#[doc(inline)]
81pub use musli_core::alloc::{Allocator, RawVec};
82
83#[cfg(feature = "alloc")]
84mod system;
85
86#[cfg(feature = "alloc")]
87#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
88pub use self::system::System;
89
90/// The static system allocator instance.
91#[cfg(feature = "alloc")]
92pub static SYSTEM: System = System::new();
93
94mod disabled;
95#[doc(inline)]
96pub use self::disabled::Disabled;
97
98mod stack;
99#[doc(inline)]
100pub use self::stack::Slice;
101
102mod array_buffer;
103pub use self::array_buffer::ArrayBuffer;
104
105mod string;
106pub(crate) use self::string::collect_string;
107#[doc(inline)]
108pub use self::string::String;
109
110mod vec;
111#[doc(inline)]
112pub use self::vec::Vec;
113
114/// The default stack buffer size for the default allocator provided through
115/// [`default!`].
116pub const DEFAULT_ARRAY_BUFFER: usize = 4096;
117
118#[macro_export]
119#[doc(hidden)]
120macro_rules! __default {
121    (|$alloc:ident| $body:block) => {
122        $crate::alloc::__default_allocator_impl!(|$alloc| $body)
123    };
124}
125
126/// Call the given block `$body` with the default allocator.
127///
128/// This is useful if you want to write application which are agnostic to
129/// whether the `alloc` feature is or isn't enabled.
130///
131/// * If the `alloc` feature is enabled, this is the [`System`] allocator.
132/// * If the `alloc` feature is disabled, this is the [`Slice`] allocator with
133///   [`DEFAULT_ARRAY_BUFFER`] bytes allocated on the stack.
134///
135/// # Examples
136///
137/// ```
138/// use musli::alloc::Vec;
139///
140/// musli::alloc::default!(|alloc| {
141///     let mut a = Vec::new_in(alloc);
142///     let mut b = Vec::new_in(alloc);
143///
144///     b.write(b"He11o");
145///     a.write(b.as_slice());
146///
147///     assert_eq!(a.as_slice(), b"He11o");
148///     assert_eq!(a.len(), 5);
149///
150///     a.write(b" W0rld");
151///
152///     assert_eq!(a.as_slice(), b"He11o W0rld");
153///     assert_eq!(a.len(), 11);
154///
155///     let mut c = Vec::new_in(alloc);
156///     c.write(b"!");
157///     a.write(c.as_slice());
158///
159///     assert_eq!(a.as_slice(), b"He11o W0rld!");
160///     assert_eq!(a.len(), 12);
161/// });
162/// ```
163#[doc(inline)]
164pub use __default as default;
165
166#[cfg(feature = "alloc")]
167#[macro_export]
168#[doc(hidden)]
169macro_rules! __default_allocator_impl {
170    (|$alloc:ident| $body:block) => {{
171        let $alloc = &$crate::alloc::SYSTEM;
172        $body
173    }};
174}
175
176#[cfg(not(feature = "alloc"))]
177#[macro_export]
178#[doc(hidden)]
179macro_rules! __default_allocator_impl {
180    (|$alloc:ident| $body:block) => {{
181        let mut __buf =
182            $crate::alloc::ArrayBuffer::<{ $crate::alloc::DEFAULT_ARRAY_BUFFER }>::new();
183        let $alloc = $crate::alloc::Slice::new(&mut __buf);
184        $body
185    }};
186}
187
188#[doc(hidden)]
189pub use __default_allocator_impl;