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
//! 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)]

#[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,
    error::SizeError,
    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};

    mod chunks;
    mod ext;
    mod iter_move;
}

// === private but reexported ===
mod array;
mod error;
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;