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;