alloc/
lib.rs

1//! # `alloc-facade`: std-or-alloc API Facade
2//!
3//! The `alloc` crate is often used in crates that are *almost*
4//! `no_std`-compatible and only need allocation capabilities to do their thing.
5//! The problem one usually faces when developing one of these "maybe std, maybe
6//! alloc" crates is that for the `std` variant, everything is available either
7//! in the prelude or at `std::` paths, while in `alloc`-only situations, the
8//! prelude must be imported manually and everything lives under `alloc::` paths.
9//!
10//! To work around this, one could simply have `#[cfg(...)]` conditionals over
11//! all of the imports as needed, but this quickly gets ugly and unwieldy. A
12//! better approach is to use a facade which re-exports the api from either `std`
13//! or `alloc`, whichever happens to be in use at the time.
14//!
15//! This crate provides such a facade. Simply make sure that one of either its
16//! `std` or `alloc` features is enabled and it provides the same importable API
17//! structure for either case. Optionally, the `futures` feature can also be
18//! enabled to provide the `task` module.
19//!
20//! ### The `setup_imports` macro
21//!
22//! Rather than use this facade crate directly, one could also use the
23//! [`setup_imports`] macro which will generate a similar facade in your own crate.
24//! This is useful if the conditions for enabling `no_std` and `alloc` are more
25//! complicated than a simple feature flag. See its documentation for more details.
26
27#![cfg_attr(not(feature = "std"), no_std)]
28
29/// Create the `alloc` api facade
30///
31/// This will add the `extern crate` declaration for the alloc crate and
32/// set up the facade module at `crate::alloc`. It should contain an identical API
33/// surface for both `std` and `alloc` uses.
34///
35/// # Example
36///
37/// ```rust,ignore
38/// #![cfg_attr(not(feature = "std"), no_std)]
39///
40/// // Each of std, alloc, and futures should be followed by a "meta" item.
41/// // This will be used for the proper #[cfg(...)] attributes.
42/// // They can be in any order. futures is optional, and will default to
43/// // "always disabled". You can use "all()" for "always enabled" on any of them.
44/// alloc::setup_imports! {
45///     std: feature = "std",
46///     alloc: feature = "alloc",
47///     futures: feature = "futures",
48/// }
49/// ```
50#[macro_export]
51macro_rules! setup_imports {
52    (@reordered $std:meta, $alloc:meta, $futures:meta ) => {
53        #[allow(unused_imports)]
54        #[cfg($alloc)]
55        pub extern crate alloc as alloc_crate;
56
57        #[cfg(any($alloc, $std))]
58        mod alloc {
59            #[cfg(all(not($std), $alloc))]
60            /// Copy of the unstable alloc prelude
61            pub mod prelude {
62                pub mod v1 {
63                    pub use super::super::borrow::ToOwned;
64                    pub use super::super::boxed::Box;
65                    pub use super::super::string::String;
66                    pub use super::super::string::ToString;
67                    pub use super::super::vec::Vec;
68                }
69            }
70
71            #[cfg(all(not($std), $alloc))]
72            pub use alloc_crate::{
73                alloc, borrow, boxed, collections, fmt, rc, slice, str,
74                string, sync, vec, format
75            };
76
77            #[cfg(all($std, not($alloc)))]
78            pub use std::{
79                alloc, borrow, boxed, collections, fmt, prelude, rc, slice, str,
80                string, vec, format,
81            };
82            #[cfg(all($std, not($alloc)))]
83            pub mod sync {
84                //! Thread-safe reference-counting pointers
85                pub use std::sync::{Arc, Weak};
86            }
87            #[cfg(all($std, not($alloc), $futures))]
88            pub use std::task;
89        }
90    };
91    (@reorder
92        ({}, $alloc:tt, $futures:tt)
93        std: $std:meta,
94        $( $tail:tt )*
95    ) => {
96        $crate::setup_imports!(@reorder ({$std}, $alloc, $futures) $($tail)*);
97    };
98    (@reorder
99        ($std:tt, {}, $futures:tt)
100        alloc: $alloc:meta,
101        $( $tail:tt )*
102    ) => {
103        $crate::setup_imports!(@reorder ($std, {$alloc}, $futures) $($tail)*);
104    };
105    (@reorder
106        ($std:tt, $alloc:tt, {})
107        futures: $futures:meta,
108        $( $tail:tt )*
109    ) => {
110        $crate::setup_imports!(@reorder ($std, $alloc, {$futures}) $($tail)*);
111    };
112    (@reorder
113        ({$std:meta}, {$alloc:meta}, {$futures:meta})
114    ) => {
115        $crate::setup_imports!(@reordered $std, $alloc, $futures);
116    };
117    (@reorder
118        ({$std:meta}, {$alloc:meta}, {})
119    ) => {
120        $crate::setup_imports!(@reordered $std, $alloc, any());
121    };
122    ($($featname:ident : $cond:meta),* $(,)* ) => {
123        $crate::setup_imports!(@reorder ({}, {}, {}) $($featname : $cond,)*);
124    };
125}
126
127crate::setup_imports! {
128    std: feature = "std",
129    alloc: feature = "alloc",
130    futures: feature = "futures",
131}
132
133#[cfg(any(feature = "alloc", feature = "std"))]
134pub use crate::alloc::*;