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}