| 1 | //! `static` friendly data structures that don't require dynamic memory allocation |
| 2 | //! |
| 3 | //! The core principle behind `heapless` is that its data structures are backed by a *static* memory |
| 4 | //! allocation. For example, you can think of `heapless::Vec` as an alternative version of |
| 5 | //! `std::Vec` with fixed capacity and that can't be re-allocated on the fly (e.g. via `push`). |
| 6 | //! |
| 7 | //! All `heapless` data structures store their memory allocation *inline* and specify their capacity |
| 8 | //! via their type parameter `N`. This means that you can instantiate a `heapless` data structure on |
| 9 | //! the stack, in a `static` variable, or even in the heap. |
| 10 | //! |
| 11 | //! ``` |
| 12 | //! use heapless::Vec; // fixed capacity `std::Vec` |
| 13 | //! |
| 14 | //! // on the stack |
| 15 | //! let mut xs: Vec<u8, 8> = Vec::new(); // can hold up to 8 elements |
| 16 | //! xs.push(42).unwrap(); |
| 17 | //! assert_eq!(xs.pop(), Some(42)); |
| 18 | //! |
| 19 | //! // in a `static` variable |
| 20 | //! static mut XS: Vec<u8, 8> = Vec::new(); |
| 21 | //! |
| 22 | //! let xs = unsafe { &mut XS }; |
| 23 | //! |
| 24 | //! xs.push(42); |
| 25 | //! assert_eq!(xs.pop(), Some(42)); |
| 26 | //! |
| 27 | //! // in the heap (though kind of pointless because no reallocation) |
| 28 | //! let mut ys: Box<Vec<u8, 8>> = Box::new(Vec::new()); |
| 29 | //! ys.push(42).unwrap(); |
| 30 | //! assert_eq!(ys.pop(), Some(42)); |
| 31 | //! ``` |
| 32 | //! |
| 33 | //! Because they have fixed capacity `heapless` data structures don't implicitly reallocate. This |
| 34 | //! means that operations like `heapless::Vec.push` are *truly* constant time rather than amortized |
| 35 | //! constant time with potentially unbounded (depends on the allocator) worst case execution time |
| 36 | //! (which is bad / unacceptable for hard real time applications). |
| 37 | //! |
| 38 | //! `heapless` data structures don't use a memory allocator which means no risk of an uncatchable |
| 39 | //! Out Of Memory (OOM) condition while performing operations on them. It's certainly possible to |
| 40 | //! run out of capacity while growing `heapless` data structures, but the API lets you handle this |
| 41 | //! possibility by returning a `Result` on operations that may exhaust the capacity of the data |
| 42 | //! structure. |
| 43 | //! |
| 44 | //! List of currently implemented data structures: |
| 45 | //! |
| 46 | # -- like `std::sync::Arc` but backed by a lock-free memory pool rather than `#[global_allocator]`" |
| 49 | )] |
| 50 | # -- like `std::boxed::Box` but backed by a lock-free memory pool rather than `#[global_allocator]`" |
| 53 | )] |
| 54 | //! - [`BinaryHeap`] -- priority queue |
| 55 | //! - [`IndexMap`] -- hash table |
| 56 | //! - [`IndexSet`] -- hash set |
| 57 | //! - [`LinearMap`] |
| 58 | # -- objects managed by an object pool" |
| 61 | )] |
| 62 | //! - [`String`] |
| 63 | //! - [`Vec`] |
| 64 | //! - [`mpmc::Q*`](mpmc) -- multiple producer multiple consumer lock-free queue |
| 65 | //! - [`spsc::Queue`] -- single producer single consumer lock-free queue |
| 66 | //! |
| 67 | //! # Optional Features |
| 68 | //! |
| 69 | //! The `heapless` crate provides the following optional Cargo features: |
| 70 | //! |
| 71 | //! - `ufmt`: Implement [`ufmt_write::uWrite`] for `String<N>` and `Vec<u8, N>` |
| 72 | //! |
| 73 | //! [`ufmt_write::uWrite`]: https://docs.rs/ufmt-write/ |
| 74 | //! |
| 75 | //! # Minimum Supported Rust Version (MSRV) |
| 76 | //! |
| 77 | //! This crate does *not* have a Minimum Supported Rust Version (MSRV) and may make use of language |
| 78 | //! features and API in the standard library available in the latest stable Rust version. |
| 79 | //! |
| 80 | //! In other words, changes in the Rust version requirement of this crate are not considered semver |
| 81 | //! breaking change and may occur in patch version releases. |
| 82 | #![cfg_attr (docsrs, feature(doc_cfg), feature(doc_auto_cfg))] |
| 83 | #![cfg_attr (not(test), no_std)] |
| 84 | #![deny (missing_docs)] |
| 85 | #![deny (warnings)] |
| 86 | |
| 87 | pub use binary_heap::BinaryHeap; |
| 88 | pub use deque::Deque; |
| 89 | pub use histbuf::{HistoryBuffer, OldestOrdered}; |
| 90 | pub use indexmap::{ |
| 91 | Bucket, Entry, FnvIndexMap, IndexMap, Iter as IndexMapIter, IterMut as IndexMapIterMut, |
| 92 | Keys as IndexMapKeys, OccupiedEntry, Pos, VacantEntry, Values as IndexMapValues, |
| 93 | ValuesMut as IndexMapValuesMut, |
| 94 | }; |
| 95 | pub use indexset::{FnvIndexSet, IndexSet, Iter as IndexSetIter}; |
| 96 | pub use linear_map::LinearMap; |
| 97 | pub use string::String; |
| 98 | pub use vec::Vec; |
| 99 | |
| 100 | #[macro_use ] |
| 101 | #[cfg (test)] |
| 102 | mod test_helpers; |
| 103 | |
| 104 | mod deque; |
| 105 | mod histbuf; |
| 106 | mod indexmap; |
| 107 | mod indexset; |
| 108 | mod linear_map; |
| 109 | mod string; |
| 110 | mod vec; |
| 111 | |
| 112 | #[cfg (feature = "serde" )] |
| 113 | mod de; |
| 114 | #[cfg (feature = "serde" )] |
| 115 | mod ser; |
| 116 | |
| 117 | pub mod binary_heap; |
| 118 | #[cfg (feature = "defmt-03" )] |
| 119 | mod defmt; |
| 120 | #[cfg (any( |
| 121 | // assume we have all atomics available if we're using portable-atomic |
| 122 | feature = "portable-atomic" , |
| 123 | // target has native atomic CAS (mpmc_large requires usize, otherwise just u8) |
| 124 | all(feature = "mpmc_large" , target_has_atomic = "ptr" ), |
| 125 | all(not(feature = "mpmc_large" ), target_has_atomic = "8" ) |
| 126 | ))] |
| 127 | pub mod mpmc; |
| 128 | #[cfg (any(arm_llsc, target_arch = "x86" ))] |
| 129 | pub mod pool; |
| 130 | pub mod sorted_linked_list; |
| 131 | #[cfg (any( |
| 132 | // assume we have all atomics available if we're using portable-atomic |
| 133 | feature = "portable-atomic" , |
| 134 | // target has native atomic CAS. Note this is too restrictive, spsc requires load/store only, not CAS. |
| 135 | // This should be `cfg(target_has_atomic_load_store)`, but that's not stable yet. |
| 136 | target_has_atomic = "ptr" , |
| 137 | // or the current target is in a list in build.rs of targets known to have load/store but no CAS. |
| 138 | has_atomic_load_store |
| 139 | ))] |
| 140 | pub mod spsc; |
| 141 | |
| 142 | #[cfg (feature = "ufmt" )] |
| 143 | mod ufmt; |
| 144 | |
| 145 | mod sealed; |
| 146 | |