allocator_fallback/lib.rs
1/*
2 * Copyright 2022 taylor.fish <contact@taylor.fish>
3 *
4 * This file is part of allocator-fallback.
5 *
6 * allocator-fallback is licensed under the Apache License, Version 2.0
7 * (the "License"); you may not use allocator-fallback except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#![cfg_attr(not(any(feature = "std", doc)), no_std)]
20#![cfg_attr(feature = "allocator_api", feature(allocator_api))]
21#![cfg_attr(feature = "doc_cfg", feature(doc_cfg))]
22#![deny(unsafe_op_in_unsafe_fn)]
23
24//! This crate provides a minimal fallback for the standard library’s allocator
25//! API, which is currently unstable.
26//!
27//! Usage
28//! -----
29//!
30//! Because allocator-fallback can be configured to re-export the real
31//! unstable allocator API (see [Crate features](#crate-features)), users
32//! of this crate must make sure they conditionally enable
33//! `#![feature(allocator_api)]` in preparation for this occurrence; otherwise,
34//! compilation errors may occur. This is the case even for crates that never
35//! directly enable allocator-fallback’s `allocator_api` feature, because a
36//! different crate that also depends on allocator-fallback could enable it.
37//!
38//! To accomplish this, in `Cargo.toml`, duplicate your dependency on
39//! `allocator-fallback` in the `[build-dependencies]` section. For example:
40//!
41//! ```toml
42//! [dependencies]
43//! allocator-fallback = "0.1.7"
44//!
45//! [build-dependencies]
46//! allocator-fallback = "0.1.7"
47//! ```
48//!
49//! Then, add a [build script][build] (`build.rs`) with the following
50//! contents:[^1]
51//!
52//! [build]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
53//!
54//! ```rust
55//! fn main() {
56//! if allocator_fallback::HAS_ALLOCATOR_API {
57//! println!("cargo:rustc-cfg=has_allocator_api");
58//! }
59//! println!("cargo:rerun-if-changed=build.rs");
60//! }
61//! ```
62//!
63//! Finally, at the top of your crate root (likely `lib.rs` or `main.rs`), add
64//! the following:
65//!
66//! ```rust
67//! #![cfg_attr(has_allocator_api, feature(allocator_api))]
68//! ```
69//!
70//! ### Use as an optional dependency
71//!
72//! The instructions above will not work if `allocator-fallback` is declared
73//! as an optional dependency. In this case, adjust the instructions as
74//! follows:
75//!
76//! Duplicate the dependency on `allocator-fallback` in `[build-dependencies]`
77//! as before, keeping `optional = true` in both occurrences. For example:
78//!
79//! ```toml
80//! [dependencies.allocator-fallback]
81//! version = "0.1.7"
82//! optional = true
83//!
84//! [build-dependencies.allocator-fallback]
85//! version = "0.1.7"
86//! optional = true
87//! ```
88//!
89//! Then, use the following as the contents of your build script (`build.rs`)
90//! instead:[^1]
91//!
92//! ```rust
93//! fn main() {
94//! #[cfg(feature = "allocator-fallback")]
95//! if allocator_fallback::HAS_ALLOCATOR_API {
96//! println!("cargo:rustc-cfg=has_allocator_api");
97//! }
98//! println!("cargo:rerun-if-changed=build.rs");
99//! }
100//! ```
101//!
102//! Finally, as before, add the following to the top of your crate root:
103//!
104//! ```rust
105//! #![cfg_attr(has_allocator_api, feature(allocator_api))]
106//! ```
107//!
108//! [^1]: These build script code snippets have been released to the public
109//! domain using the [CC0 1.0 Universal Public Domain Dedication][CC0].
110//!
111//! [CC0]: https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt
112//!
113//! Crate features
114//! --------------
115//!
116//! If the crate feature `allocator_api` is enabled, this crate will simply
117//! re-export the real allocator API in the standard library. Of course, this
118//! requires Rust nightly.
119//!
120//! If the crate feature `std` is enabled (the default), the crate will use
121//! [`std`]; otherwise, it will be `no_std`. Using [`std`] allows
122//! [`AllocError`] to implement [`std::error::Error`].
123
124extern crate alloc;
125
126#[cfg(not(feature = "allocator_api"))]
127mod fallback;
128
129#[cfg(not(feature = "allocator_api"))]
130pub use fallback::{AllocError, Allocator, Global};
131
132#[cfg(feature = "allocator_api")]
133pub use alloc::alloc::{AllocError, Allocator, Global};
134
135/// For use in build scripts. See [Usage](crate#usage).
136pub const HAS_ALLOCATOR_API: bool = cfg!(has_allocator_api);
137
138#[test]
139fn test() {
140 use alloc::alloc::Layout;
141 let _: &dyn Allocator = &Global;
142 let ptr = Global.allocate(Layout::new::<u64>()).unwrap();
143 unsafe {
144 ptr.cast::<u64>().as_ptr().write(0x123456789abcdef);
145 (&&&Global).deallocate(ptr.cast(), Layout::new::<u64>());
146 }
147}