konst/array.rs
1//! Const equivalents of array functions.
2
3macro_rules! leak_warning {
4 () => {
5 concat!(
6 "# Warning\n",
7 "\n",
8 "This macro leaks the initialized part of the array\n",
9 "if the closure passed to this macro panics or returns early.\n",
10 "\n",
11 "note: this warning is not relevant if the elements don't need dropping",
12 "(e.g: by implementing `Copy`).\n"
13 )
14 };
15}
16use leak_warning;
17
18/// Superceeded by [`map_`],
19/// const version of [`array::map`](https://doc.rust-lang.org/std/primitive.array.html#method.map).
20///
21#[doc = leak_warning!()]
22///
23/// # Limitations
24///
25/// This macro supports mapping from non-Copy arrays if any of these
26/// conditions are met about the parameter of the passed-in closure:
27/// 1. it's a pattern that only copies Copy fields of each array element
28/// 2. it's a `ref` pattern
29///
30/// [examples of both of the above conditions below](#map-noncopy-example)
31///
32/// # Example
33///
34/// ### Basic
35///
36/// ```rust
37/// use konst::array;
38///
39/// const TRIMMED: [&str; 3] = array::map!([" foo", "bar ", " baz "], konst::string::trim);
40/// assert_eq!(TRIMMED, ["foo", "bar", "baz"]);
41///
42/// const LENGTHS: [usize; 3] = array::map!(["foo", "hello", "bar baz"], |s| s.len());
43/// assert_eq!(LENGTHS, [3, 5, 7]);
44///
45/// const SQUARED: [u32; 6] = array::map!([1, 2, 3, 4, 5, 6], |x: u32| x.pow(2));
46/// assert_eq!(SQUARED, [1, 4, 9, 16, 25, 36]);
47///
48/// {
49/// let input = [3, 5, 8];
50/// let output = array::map!(input, |x| -> u64 { x + 2 });
51/// assert_eq!(output, [5, 7, 10]);
52/// }
53///
54/// ```
55///
56/// <span id="map-noncopy-example"> </span>
57/// ### Map from non-Copy array
58///
59/// Demonstrates both ways to map from a non-Copy array.
60///
61/// ```rust
62/// use konst::array;
63///
64/// struct NonCopy(u32, u32);
65///
66/// const PRIME_SUMS: [u32; 3] = {
67/// let input = [NonCopy(2, 3), NonCopy(5, 7), NonCopy(11, 13)];
68///
69/// // demonstrates the first way to map from non-Copy elements
70/// array::map!(input, |NonCopy(l, r)| l + r)
71/// };
72/// assert_eq!(PRIME_SUMS, [5, 12, 24]);
73///
74/// const FIBB_SUMS: [u32; 3] = {
75/// let input = [NonCopy(2, 3), NonCopy(5, 8), NonCopy(13, 21)];
76///
77/// // demonstrates the second way to map from non-Copy elements
78/// array::map!(input, |ref nc| nc.0 + nc.1)
79/// };
80/// assert_eq!(FIBB_SUMS, [5, 13, 34]);
81///
82/// ```
83///
84pub use konst_kernel::array_map as map;
85
86#[cfg(feature = "rust_1_83")]
87#[doc(hidden)]
88pub mod __array_macros_2;
89
90#[cfg(feature = "rust_1_83")]
91mod array_builder;
92
93#[cfg(feature = "rust_1_83")]
94mod array_consumer;
95
96#[cfg(feature = "rust_1_83")]
97#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
98pub use self::{
99 array_builder::ArrayBuilder,
100 array_consumer::ArrayConsumer,
101};
102
103
104
105
106#[cfg(feature = "rust_1_83")]
107macro_rules! drop_warning {
108 () => {
109 concat!(
110 "# Note",
111 "\n\n",
112 "`return` inside the closure passed to this macro ",
113 "attempts to return from the function where this macro is called, ",
114 "which drops the array elements, ",
115 "and dropping isn't allowed in const as of Rust 1.83.0.",
116 "\n\n",
117 "The same applies to `?`, ",
118 "and labelled `break`/`continue` into labels from outside the closure.",
119 )
120 };
121}
122
123#[cfg(feature = "rust_1_83")]
124use drop_warning;
125
126/// Const equivalent of
127/// [`array::map`](https://doc.rust-lang.org/std/primitive.array.html#method.map)
128///
129#[doc = drop_warning!()]
130///
131/// # Example
132///
133/// ```rust
134/// assert_eq!(PAIRS, [(3, "hello"), (5, "world"), (8, "foo")]);
135///
136/// const PAIRS: [(u8, &str); 3] =
137/// swap_pairs([("hello", 3), ("world", 5), ("foo", 8)]);
138///
139/// const fn swap_pairs<T, U, const N: usize>(pairs: [(T, U); N]) -> [(U, T); N] {
140/// konst::array::map_!(pairs, |pair: (T, U)| {
141/// // need to use `destructure` to destructure types that may contain Drop fields
142/// konst::destructure!{(a, b) = pair}
143/// (b, a)
144/// })
145/// }
146/// ```
147///
148#[doc(inline)]
149#[cfg(feature = "rust_1_83")]
150#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
151pub use crate::__array_map_by_val as map_;
152
153/// Superceeded by [`from_fn_`], const version of
154/// [`array::from_fn`](core::array::from_fn).
155///
156#[doc = leak_warning!()]
157///
158/// # Example
159///
160/// ```rust
161/// use konst::array;
162///
163/// {
164/// const POWERS: [u64; 5] = array::from_fn!(|i| 2u64.pow(i as u32));
165///
166/// assert_eq!(POWERS, [1, 2, 4, 8, 16]);
167/// }
168///
169/// // Annotating the array type
170/// assert_eq!(
171/// array::from_fn!([&str; 6] => |i| konst::string::str_up_to("hello", i)),
172/// ["", "h", "he", "hel", "hell", "hello"],
173/// );
174/// ```
175///
176pub use konst_kernel::array_from_fn as from_fn;
177
178/// Const equivalent of [`array::from_fn`](core::array::from_fn).
179///
180#[doc = drop_warning!()]
181///
182///
183/// # Example
184///
185/// ```rust
186/// use konst::array;
187///
188/// {
189/// const POWERS: [u64; 5] = array::from_fn_!(|i| 2u64.pow(i as u32));
190///
191/// assert_eq!(POWERS, [1, 2, 4, 8, 16]);
192/// }
193///
194/// // Annotating the array type
195/// assert_eq!(
196/// array::from_fn_!([&str; 6] => |i| konst::string::str_up_to("hello", i)),
197/// ["", "h", "he", "hel", "hell", "hello"],
198/// );
199/// ```
200///
201#[doc(inline)]
202#[cfg(feature = "rust_1_83")]
203#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
204pub use crate::__array_from_fn2 as from_fn_;