konst/slice.rs
1//! `const fn` equivalents of slice methods.
2
3/// `const fn`s for comparing slices for equality and ordering.
4#[cfg(feature = "cmp")]
5#[cfg_attr(feature = "docsrs", doc(cfg(feature = "cmp")))]
6pub mod cmp;
7
8mod slice_const_methods;
9mod slice_iter_methods;
10
11pub use slice_const_methods::*;
12pub use slice_iter_methods::*;
13
14__declare_slice_cmp_fns! {
15 import_path = "konst",
16
17 (
18 ///
19 /// # Example
20 ///
21 ,
22 /// ```rust
23 /// use konst::slice::eq_bytes;
24 ///
25 /// const FOO: &[u8] = b"foo";
26 /// const BAR: &[u8] = b"fooooo";
27 /// const BAZ: &[u8] = b"bar";
28 ///
29 ///
30 /// const FOO_EQ_FOO: bool = eq_bytes(FOO, FOO);
31 /// assert!( FOO_EQ_FOO );
32 ///
33 /// const FOO_EQ_BAR: bool = eq_bytes(FOO, BAR);
34 /// assert!( !FOO_EQ_BAR );
35 ///
36 /// const FOO_EQ_BAZ: bool = eq_bytes(FOO, BAZ);
37 /// assert!( !FOO_EQ_BAZ );
38 ///
39 /// ```
40 ///
41 ,
42 /// ```rust
43 /// use konst::slice::cmp_bytes;
44 ///
45 /// use std::cmp::Ordering;
46 ///
47 /// const FOO: &[u8] = b"foo";
48 /// const BAR: &[u8] = b"fooooo";
49 /// const BAZ: &[u8] = b"bar";
50 ///
51 ///
52 /// const FOO_CMP_FOO: Ordering = cmp_bytes(FOO, FOO);
53 /// assert_eq!(FOO_CMP_FOO, Ordering::Equal);
54 ///
55 /// const FOO_CMP_BAR: Ordering = cmp_bytes(FOO, BAR);
56 /// assert_eq!(FOO_CMP_BAR, Ordering::Less);
57 ///
58 /// const FOO_CMP_BAZ: Ordering = cmp_bytes(FOO, BAZ);
59 /// assert_eq!(FOO_CMP_BAZ, Ordering::Greater);
60 ///
61 /// ```
62 ///
63 ,
64 u8,
65 eq_bytes,
66 cmp_bytes,
67 )
68}
69
70__declare_fns_with_docs! {
71 (Option<&'a [u8]>, (eq_option_bytes, cmp_option_bytes))
72
73 docs(default)
74
75 macro = __impl_option_cmp_fns!(
76 for['a,]
77 params(l, r)
78 eq_comparison = eq_bytes(l, r),
79 cmp_comparison = cmp_bytes(l, r),
80 parameter_copyability = copy,
81 ),
82}
83
84/// Tries to convert from `&[T]` to `&[T; N]`, usable in `const`s, but not in `const fn`s.
85///
86/// Evaluates to an `Err(TryIntoArrayError{..})` when the slice doesn't match the expected length.
87///
88/// For an alternative that can be used in `const fn`s, there is the [`try_into_array`] function,
89/// but it can only be used with the nightly compiler.
90///
91/// # Features
92///
93/// By default you need to pass the length of the returned array.
94///
95/// To infer the length of the array you need to enable the `"rust_1_51"` feature,
96/// which requires Rust 1.51.0
97///
98/// # Example
99///
100/// ### Explicit length
101///
102/// ```rust
103/// use konst::{
104/// slice::{TryIntoArrayError, try_into_array},
105/// result,
106/// };
107///
108///
109/// const ARR_5: Option<&[u64; 5]> = {
110/// let slice: &[u64] = &[1, 10, 100, 1000, 10000];
111///
112/// result::ok!(try_into_array!(slice, 5))
113/// };
114///
115/// assert_eq!(ARR_5, Some(&[1, 10, 100, 1000, 10000]));
116///
117///
118/// const ERR: Result<&[u64; 5], TryIntoArrayError> = {
119/// let slice: &[u64] = &[];
120///
121/// try_into_array!(slice, 5)
122/// };
123///
124/// assert!(ERR.is_err());
125///
126/// ```
127///
128/// ### Slice constant to Array
129///
130/// ``` rust
131/// use konst::{slice, unwrap_ctx};
132///
133/// const SLICE: &[u8] = b"Hello world!";
134///
135/// static ARRAY: [u8; SLICE.len()] = *unwrap_ctx!(slice::try_into_array!(SLICE, SLICE.len()));
136///
137/// assert_eq!(ARRAY, *b"Hello world!")
138///
139/// ```
140///
141/// ### Length inference
142///
143/// `try_into_array` can infer the length of the array with the
144/// `"rust_1_51"` feature, which requires Rust 1.51.0.
145///
146#[cfg_attr(feature = "rust_1_51", doc = "```rust")]
147#[cfg_attr(not(feature = "rust_1_51"), doc = "```ignore")]
148/// use konst::{slice::try_into_array, unwrap_ctx};
149///
150/// const ARR_3: &[u64; 3] = {
151/// let slice: &[u64] = &[3, 5, 8];
152///
153/// // Letting the macro infer the length of the array,
154/// let array = unwrap_ctx!(try_into_array!(slice));
155///
156/// // You can destructure the array into its elements like this
157/// let [a, b, c] = *array;
158///
159/// array
160/// };
161///
162/// assert_eq!(ARR_3, &[3, 5, 8]);
163///
164/// ```
165///
166/// [`try_into_array`]: ./fn.try_into_array.html
167/// [`include_bytes`]: https://doc.rust-lang.org/std/macro.include_bytes.html
168#[doc(inline)]
169pub use konst_macro_rules::try_into_array;
170
171/// The error produced by trying to convert from
172/// `&[T]` to `&[T; N]`, or from `&mut [T]` to `&mut [T; N]`.
173#[doc(inline)]
174pub use konst_macro_rules::slice_::TryIntoArrayError;
175
176/// Tries to convert from `&[T]` to `&[T; N]`, usable in `const fn`s.
177/// Requires the `"rust_1_56"` feature.
178///
179/// Returns an `Err(TryIntoArrayError{..})` when the slice doesn't match the expected length.
180///
181/// For an alternative that works on stable Rust, there is the [`try_into_array`] macro,
182/// but it can only be used in `const`s, not in `const fn`s .
183///
184/// # Example
185///
186/// ```rust
187/// use konst::{
188/// slice::{TryIntoArrayError, try_into_array},
189/// result,
190/// unwrap_ctx,
191/// };
192///
193///
194/// const fn arr_5() -> Option<&'static [u64; 5]> {
195/// let slice: &[u64] = &[1, 10, 100, 1000, 10000];
196///
197/// // Passing the length explicitly to the function
198/// result::ok!(try_into_array::<_, 5>(slice))
199/// }
200///
201/// assert_eq!(arr_5(), Some(&[1, 10, 100, 1000, 10000]));
202///
203///
204/// const fn err() -> Result<&'static [u64; 5], TryIntoArrayError> {
205/// let slice: &[u64] = &[];
206///
207/// // Letting the function infer the length of the array,
208/// try_into_array(slice)
209/// }
210///
211/// assert!(err().is_err());
212///
213///
214/// const fn arr_3() -> &'static [u64; 3] {
215/// let slice: &[u64] = &[3, 5, 8];
216///
217/// let array = unwrap_ctx!(try_into_array(slice));
218///
219/// // You can destructure the array into its elements like this
220/// let [a, b, c] = *array;
221///
222/// array
223/// }
224///
225/// assert_eq!(arr_3(), &[3, 5, 8]);
226///
227/// ```
228///
229/// [`try_into_array`]: ./macro.try_into_array.html
230#[cfg(feature = "rust_1_56")]
231#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
232#[doc(inline)]
233pub use konst_macro_rules::slice_::try_into_array_func as try_into_array;
234
235/// Tries to convert from `&mut [T]` to `&mut [T; N]`.
236///
237/// Returns an `Err(TryIntoArrayError{..})` when the slice doesn't match the expected length.
238///
239/// # Example
240///
241/// ```rust
242/// # #![feature(const_mut_refs)]
243/// use konst::{slice, unwrap_ctx};
244///
245/// const fn mut_array_from<const LEN: usize>(slice: &mut [u8], from: usize) -> &mut [u8; LEN] {
246/// let sliced = slice::slice_range_mut(slice, from, from + LEN);
247/// unwrap_ctx!(slice::try_into_array_mut(sliced))
248/// }
249///
250/// # fn main() {
251///
252/// let slice = &mut [3, 5, 8, 13, 21, 34, 55, 89, 144, 233];
253///
254/// let foo: &mut [u8; 2] = mut_array_from(slice, 0);
255/// assert_eq!(foo, &mut [3, 5]);
256///
257/// let bar: &mut [u8; 3] = mut_array_from(slice, 2);
258/// assert_eq!(bar, &mut [8, 13, 21]);
259///
260/// let baz: &mut [u8; 4] = mut_array_from(slice, 4);
261/// assert_eq!(baz, &mut [21, 34, 55, 89]);
262///
263/// # }
264/// ```
265///
266#[cfg(feature = "mut_refs")]
267#[cfg_attr(
268 feature = "docsrs",
269 doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
270)]
271#[doc(inline)]
272pub use konst_macro_rules::slice_::try_into_array_mut_func as try_into_array_mut;