musli_allocator/lib.rs
1//! [<img alt="github" src="https://img.shields.io/badge/github-udoprog/musli-8da0cb?style=for-the-badge&logo=github" height="20">](https://github.com/udoprog/musli)
2//! [<img alt="crates.io" src="https://img.shields.io/crates/v/musli-allocator.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/musli-allocator)
3//! [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-musli--allocator-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/musli-allocator)
4//!
5//! Allocation support for [Müsli].
6//!
7//! This crate contains two types of allocators:
8//! * The [`System`] allocator, which uses the system allocation facilities.
9//! Particularly [`std::alloc::System`].
10//! * The [`Stack`] allocator, which can allocate buffers from a fixed-size
11//! slice.
12//!
13//! <br>
14//!
15//! ## Examples
16//!
17//! ```
18//! use musli::{Allocator, Buf};
19//!
20//! musli_allocator::with(|alloc| {
21//! let mut a = alloc.alloc().expect("allocation a failed");
22//! let mut b = alloc.alloc().expect("allocation b failed");
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 = alloc.alloc().expect("allocation c failed");
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//! [Müsli]: <https://docs.rs/musli>
45//! [`std::alloc::System`]: https://doc.rust-lang.org/std/alloc/struct.System.html
46
47#![deny(missing_docs)]
48#![no_std]
49#![cfg_attr(doc_cfg, feature(doc_cfg))]
50
51#[cfg_attr(test, macro_use)]
52#[cfg(feature = "std")]
53extern crate std;
54
55#[cfg(feature = "alloc")]
56extern crate alloc;
57
58#[cfg(test)]
59mod tests;
60
61#[cfg(feature = "alloc")]
62mod system;
63
64#[cfg(feature = "alloc")]
65#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
66pub use self::system::System;
67
68mod disabled;
69pub use self::disabled::Disabled;
70
71mod stack;
72#[doc(inline)]
73pub use self::stack::{Stack, StackBuffer};
74
75/// The default stack buffer size for the default allocator provided through
76/// [`with`].
77pub const DEFAULT_STACK_BUFFER: usize = 4096;
78
79/// The default allocator.
80#[cfg(feature = "alloc")]
81pub type Default<'a> = System;
82
83/// The default allocator.
84#[cfg(not(feature = "alloc"))]
85pub type Default<'a> = Stack<'a>;
86
87/// Call the given closure with the default allocator.
88///
89/// This is useful if you want to write application which are agnostic to
90/// whether the `alloc` feature is or isn't enabled.
91///
92/// * If the `alloc` feature is enabled, this is the [`System`] allocator.
93/// * If the `alloc` feature is disabled, this is the [`Stack`] allocator with
94/// [`DEFAULT_STACK_BUFFER`] bytes allocated on the stack.
95///
96/// # Examples
97///
98/// ```
99/// use musli::{Allocator, Buf};
100///
101/// musli_allocator::with(|alloc| {
102/// let mut a = alloc.alloc().expect("allocation a failed");
103/// let mut b = alloc.alloc().expect("allocation b failed");
104///
105/// b.write(b"He11o");
106/// a.write(b.as_slice());
107///
108/// assert_eq!(a.as_slice(), b"He11o");
109/// assert_eq!(a.len(), 5);
110///
111/// a.write(b" W0rld");
112///
113/// assert_eq!(a.as_slice(), b"He11o W0rld");
114/// assert_eq!(a.len(), 11);
115///
116/// let mut c = alloc.alloc().expect("allocation c failed");
117/// c.write(b"!");
118/// a.write(c.as_slice());
119///
120/// assert_eq!(a.as_slice(), b"He11o W0rld!");
121/// assert_eq!(a.len(), 12);
122/// });
123/// ```
124#[inline(always)]
125#[track_caller]
126pub fn with<F, O>(f: F) -> O
127where
128 F: FnOnce(&Default<'_>) -> O,
129{
130 with_impl(f)
131}
132
133#[cfg(feature = "alloc")]
134#[inline(always)]
135#[track_caller]
136fn with_impl<F, O>(f: F) -> O
137where
138 F: FnOnce(&System) -> O,
139{
140 let alloc = System::new();
141 f(&alloc)
142}
143
144#[cfg(not(feature = "alloc"))]
145#[inline(always)]
146#[track_caller]
147fn with_impl<F, O>(f: F) -> O
148where
149 F: FnOnce(&Stack<'_>) -> O,
150{
151 let mut buf = StackBuffer::<DEFAULT_STACK_BUFFER>::new();
152 let alloc = Stack::new(&mut buf);
153 f(&alloc)
154}