1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
//! This crate provides API for working with arrays, e.g.: //! 1) Abstraction over arrays (you can use [`Array`] trait as bound on //! generics) //! 2) Creation of arrays (see [`Array`] trait) //! 3) Doing operations on arrays that produce arrays (see //! [`ArrayMap`] and [`ArrayAsRef`] traits) //! 4) By-value iterating on array (see [`IterMove`]) //! 5) `Iterator` adapter that yield fixed sized chunks of inner iterator //! (see [`ArrayChunks`]) //! //! [`Array`]: crate::Array //! [`ArrayExt`]: crate::ArrayExt //! [`IterMove`]: crate::iter::IterMove //! [`ArrayChunks`]: crate::iter::ArrayChunks //! //! ## Example //! //! ``` //! use arraylib::{Array, ArrayExt, ArrayMap}; //! //! // Array creation //! let arr = <[_; 11]>::unfold(1, |it| { //! let res = *it; //! *it *= -2; //! res //! }); //! //! // Mapping //! let arr = arr.map(|it| it * 2); //! assert_eq!(arr, [2, -4, 8, -16, 32, -64, 128, -256, 512, -1024, 2048]); //! //! // By-value iterator //! arr.iter_move().for_each(|i: i32| {}) //! ``` //! //! ## Sizes Limitations //! //! Because of lack of [`const generics`] it's impossible to implement traits on //! arrays of _all_ sizes (see [std note about that]), so this crate implements //! traits only for these sizes: //! - `[0; 32]` //! - `8 * [5; 12]` (40, 48, ..., 96) //! - `100 * [1; 10]` (100, 200, ..., 1000) //! - `2 ** [7; 16]` (128, 256, ..., 65536) //! - `[33; 128]` (If **array-impls-33-128** feature enabled) //! - `[129; 256]` (If **array-impls-129-256** feature enabled) //! //! [`const generics`]: https://github.com/rust-lang/rust/issues/44580 //! [std note about that]: https://doc.rust-lang.org/std/primitive.array.html //! //! ## no_std //! //! This lib doesn't depend on `std`, so it can be used in crates with the //! `#![no_std]` attribute. //! //! ## Features //! //! This crate provide next features: //! - **alloc** — enables API that depend on `alloc` crate //! - **nightly** — enable features that require nightly features: //! - `trusted_len` ([tracking issue][trusted_ti]) (Adds impl of `TrustedLen` //! for iterators) //! - `exact_size_is_empty` ([tracking issue][is_empty_ti]) (Implement //! `<{Chunks,IterMove} as ExactSizeIterator>::is_empty` more effective) //! - **array-impls-33-128** — adds impl of the [`Array`] trait for arrays of //! sizes 33-128 (inclusive) //! - **array-impls-129-256** — adds impl of the [`Array`] trait for arrays of //! sizes 129-256 (inclusive) //! //! [trusted_ti]: https://github.com/rust-lang/rust/issues/37572 //! [is_empty_ti]: https://github.com/rust-lang/rust/issues/35428 //! //! ## Alternatives //! //! Crates those provide similar API (or part of it): //! //! - [`generic_array`](https://docs.rs/generic-array) //! - [`array_init`](https://docs.rs/array-init/) (analogs to [`Array::from_fn`] //! and [`Array::from_iter`]) //! - [`array_ext`](https://docs.rs/array_ext) //! - [`slice_as_array`](https://peterreid.github.io/slice_as_array/slice_as_array/index.html) //! (analogs to [`ArrayExt::from_slice`] and [`Array::from_iter`]) //! - [`arraytools`](https://docs.rs/arraytools) //! - [`core::array::FixedSizeArray`](https://doc.rust-lang.org/beta/core/array/trait.FixedSizeArray.html) //! - [`stackvec`](https://docs.rs/stackvec/) //! - [`array_iterator`](https://docs.rs/array_iterator/) //! - [`arraymap`](https://docs.rs/arraymap/) //! //! [`Array::from_fn`]: crate::Array::from_fn //! [`Array::from_iter`]: crate::Array::from_iter //! //! ## Safety //! //! To achieve good performance and support so many array sizes, this //! crate uses a alot of unsafe code (by commit `079871cc` there are 17 `unsafe //! {}` blocks). All `unsafe`s were checked with care and have a "Safety" //! comment. //! //! If you see that some `unsafe`s could be removed without performance loss (we //! need benchmarks, oh) please fill an [issue]. //! //! [issue]: https://github.com/WaffleLapkin/arraylib/issues/new // We use std in tests to catch panic #![cfg_attr(not(test), no_std)] // Some sweaty nightly features #![cfg_attr(feature = "nightly", feature(trusted_len, exact_size_is_empty))] // For running tests from readme #![cfg_attr(all(doctest, feature = "nightly"), feature(external_doc))] // I hate missing docs #![deny(missing_docs)] // And I like inline #![warn(clippy::missing_inline_in_public_items)] // we pass "--cfg docsrs" when building docs to add `This is supported on feature="..." only.` // // To properly build docs of this crate run // ```console // $ RUSTDOCFLAGS="--cfg docsrs" cargo doc --open --features "alloc nightly" // ``` #![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(feature = "alloc")] extern crate alloc; /// Utils that help implementing public API #[macro_use] pub(crate) mod util { #[macro_use] /// Helper macros these are used in this lib mod local_macros; /// Array initialization pub(crate) mod init; /// `T -> U` transmute (analog to `core::mem::transmute`) pub(crate) mod transmute; } pub use self::{ array::Array, ext::{ array_ext::ArrayExt, shorthand::ArrayShorthand, slice_ext::{MaybeUninitSlice, Slice}, }, transform::{as_ref::ArrayAsRef, map::ArrayMap}, wrap::ArrayWrapper, }; /// Iterator related things pub mod iter { pub use self::{ chunks::ArrayChunks, ext::IteratorExt, iter_move::IterMove, windows::ArrayWindows, }; mod chunks; mod ext; mod iter_move; mod windows; } // === private but reexported === mod array; mod wrap; /// Array transformers like map (`[T; N]` -> `[U; N]`) /// /// Commonly just shortcuts for `.iter_move().*method*(...).collect_array()` mod transform { /// `&(mut) [T; N]` -> `[&(mut) T; N]` pub(super) mod as_ref; /// `[T; N]` -> `[U; N]` pub(super) mod map; } /// Different extension traits mod ext { /// Array ext pub(super) mod array_ext; /// Also array ext (but for `.as_slice().method()` -> `.method()` shortcuts) pub(super) mod shorthand; /// Slice ext pub(super) mod slice_ext; } /// Run tests from readme #[cfg_attr(feature = "nightly", doc(include = "../README.md"))] #[cfg(doctest)] pub struct ReadmeDocTests; /// Error that is caused by wrong sizes of slices/arrays #[derive(Debug, PartialEq, Eq, Copy, Clone, Default)] pub struct SizeError(()); impl core::fmt::Display for SizeError { #[inline] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { f.write_str("wrong size") } } /// Conditional compilation depending on whether `arraylib` is built with /// `alloc` feature. /// /// This macro is needed if you want to implement `Array` on your type (change /// your mind, you fool) which requires `into_boxed_slice` method, but only if /// `alloc` feature is enabled. /// /// When `arraylib` is built with `alloc` feature, this macro expands /// transparently into just the input tokens. /// /// ``` /// macro_rules! if_alloc { /// ($($tt:tt)*) => { /// $($tt)* /// }; /// } /// ``` /// /// When built without `alloc` feature, this macro expands to /// nothing. /// /// ``` /// macro_rules! if_alloc { /// ($($tt:tt)*) => {}; /// } /// ``` // idea is copy-pasted from serde (https://docs.serde.rs/serde/macro.serde_if_integer128.html) #[cfg(feature = "alloc")] #[macro_export] macro_rules! if_alloc { ($($tt:tt)*) => { $($tt)* }; } #[cfg(not(feature = "alloc"))] #[doc(hidden)] #[macro_export] macro_rules! if_alloc { ($($tt:tt)*) => {}; }