array_utils/
lib.rs

1//! A no_std heapless set of utilities for handling const generic arrays. Sized arrays sacrifice
2//! speed and convenience for simplicity and predictability. This is mostly used at very low levels
3//! and/or on platforms without heaps. This crate will greatly improve the readability and
4//! maintainability of code on those platforms.
5//!
6//! # Features
7//!
8//! This crate provides functions to `initialize`, `drift`, `slice`, `resize`, `splice`, `join` and
9//! `superimpose` sized arrays. All of which are _features_ enabled by default, but can therefore
10//! also be used separately. Let us go all of the _features_ one by one.
11//!
12//! This crate only contains functions which should never panic. Every invalid value given will
13//! either result in data truncating or an array being fill up with extra data. The bounds,
14//! specific behaviors and other important details are documented in each function's page.
15//!
16//! ## Initialize
17//!
18//! This feature provides 4 utility functions. These are
19//! [`initialize_from`](crate::initialize_from), [`initialize_till`](crate::initialize_till),
20//! [`initialize_from_option`](crate::initialize_from_option) and
21//! [`initialize_from_result`](crate::initialize_from_result). All these functions provide an
22//! simpler ways to initialize sized array using closures, as can be seen in their documentation.
23//!
24//! ## Drift / Superimpose
25//!
26//! The 2 drifting functions, which are [`drift_to_begin`](crate::drift_to_begin) and [`drift_to_end`](crate::drift_to_end), provide a way to
27//! float a part of the sized array to the beginning or the end of the array. This provides a
28//! solution to the common problem of prefixing or suffixing some elements to an array. It can
29//! be seen as a more optimized shortcut for the the combination of
30//! [`sized_slice`](crate::sized_slice) and
31//! [`superimpose`](crate::superimpose). There is also the more general form of [`superimpose`](crate::superimpose), which allows for one
32//! sized array to be superimposed upon another.
33//!
34//! ## Slice / Resize
35//!
36//! Ordinary slices of sized array have the disadvantage of either losing size metadata or needing
37//! a `.try_into().unwrap()` appended, which can panic. The [`sized_slice`](crate::sized_slice) utility function
38//! provides a way to deal with slicing into sized arrays which never panics. In a similar way to
39//! slicing dealing scaling arrays is rather cumbersome. [`array_resize`](crate::array_resize) provide a simple way to
40//! deal with all the truncating or expanding of data without the possibility for panics.
41//!
42//!
43//! ## Splice / Join
44//!
45//! The [`splice`](crate::splice) and [`join`](crate::join) utilities are basically more optimized combinations of
46//! [`sized_slice`](crate::sized_slice) and [`superimpose`](crate::superimpose). Making splicing and joining arrays at specific indices can
47//! be very handy for dealing with packet and data streams.
48//!
49//! # Usage
50//!
51//! Since we are using sized arrays, all utilities heavily rely on const generics. Furthermore, all
52//! functions are only implemented for types with the [`Copy`](::core::marker::Copy) trait. Some
53//! utilities, namely the functions without additional `fill` parameter, also depend on the
54//! [`Default`](::core::default::Default) trait.
55//!
56//! Here are some examples or the usage of this crate.
57//!
58//! ## Initializing
59//!
60//! ```
61//! use array_utils::initialize_from;
62//!
63//! // Use a closure which doubles the index
64//! let even_numbers: [usize; 5] = initialize_from(|index| index * 2);
65//! assert_eq!(even_numbers, [0, 2, 4, 6, 8]);
66//! ```
67//!
68//! ## Drifting
69//!
70//! ```
71//! use array_utils::{ drift_to_begin, drift_to_end };
72//!
73//! let array = [1, 2, 3, 0, 0, 0, 0];
74//! // Float the elements with indices `0..` to the beginning with a margin of `1` elements,
75//! // filling in `0x00` for all new elements.
76//! assert_eq!(drift_to_begin(array, 0, 1, 0x00), [0, 1, 2, 3, 0, 0, 0]);
77//!
78//! // Float the elements with indices `..3` to the end with a margin of `0` elements,
79//! // filling in `42` for all new elements.
80//! assert_eq!(drift_to_end(array, 3, 0, 42), [42, 42, 42, 42, 1, 2, 3]);
81//! ```
82
83#![no_std]
84#![warn(missing_docs)]
85
86const fn min_of_sizes(x: usize, y: usize) -> usize {
87    if x < y {
88        x
89    } else {
90        y
91    }
92}
93
94/// Initialize a sized array from a closure taking the index and outputting the elements.
95///
96/// Generates a new sized array generated from generator closure, which turns a index into a
97/// element of the generated array.
98///
99/// # Examples
100///
101/// ```
102/// use array_utils::initialize_from;
103///
104/// // Size is most of the time automatically inferred
105/// assert_eq!(initialize_from(|index| index), [0, 1, 2, 3, 4, 5]);
106/// assert_eq!(initialize_from(|index| 2 * index), [0, 2, 4, 6, 8, 10]);
107///
108/// fn get_prime(index: usize) -> usize {
109///     // ...snip
110///     # [2, 3, 5, 7, 9, 11][index]
111/// }
112///
113/// assert_eq!(initialize_from(get_prime), [2, 3, 5, 7, 9, 11]);
114/// ```
115///
116/// # Panics
117///
118/// Only panics when the given closure `f` panics.
119#[cfg(feature = "initialize")]
120pub fn initialize_from<T, F, const OUTPUT_SIZE: usize>(f: F) -> [T; OUTPUT_SIZE]
121where
122    T: Copy + Default,
123    F: Fn(usize) -> T,
124{
125    let mut buffer = [T::default(); OUTPUT_SIZE];
126    for i in 0..OUTPUT_SIZE {
127        buffer[i] = f(i);
128    }
129    buffer
130}
131
132/// Initialize a sized array from a closure till a certain value appears.
133///
134/// Generates a new sized array generated from generator closure, which turns a index into a
135/// element of the generated array. If the given `till` value is found, the rest of the output
136/// array is filled with the `fill` value. Along with the generated array, this utility returns
137/// at what index the given `till` value was found (`OUTPUT_SIZE` if not found).
138///
139/// # Examples
140///
141/// ```
142/// use array_utils::initialize_till;
143///
144/// let till_five: ([usize; 8], usize) = initialize_till(
145///     |index| index,  // Generator closure
146///     5,              // Till this value
147///     42              // Fill the rest with
148/// );
149/// assert_eq!(till_five, ([0, 1, 2, 3, 4, 42, 42, 42], 5));
150///
151/// // Especially useful for null terminated data streams.
152/// # static mut COUNTER: usize = 0;
153/// fn get_stream_byte() -> u8 {
154///     # unsafe {COUNTER += 1;
155///     # [0, 4, 2, 1, 3, 3, 7, 0][COUNTER]}
156///     // ...snip
157/// }
158///
159/// // Fetch stream bytes till it find a `0` byte. Fill the rest with `0` bytes.
160/// assert_eq!(initialize_till(|_| get_stream_byte(), 0, 0), ([4, 2, 1, 3, 3, 7, 0, 0, 0], 6));
161/// ```
162///
163/// # Panics
164///
165/// Only panics if the given `f` panics.
166#[cfg(feature = "initialize")]
167pub fn initialize_till<T, F, const OUTPUT_SIZE: usize>(
168    f: F,
169    till: T,
170    fill: T,
171) -> ([T; OUTPUT_SIZE], usize)
172where
173    T: Copy + PartialEq,
174    F: Fn(usize) -> T,
175{
176    let mut buffer = [fill; OUTPUT_SIZE];
177    for i in 0..OUTPUT_SIZE {
178        let value = f(i);
179        if value == till {
180            return (buffer, i);
181        }
182
183        buffer[i] = value;
184    }
185    (buffer, OUTPUT_SIZE)
186}
187
188/// Initialize a sized array from a closure taking the index and outputting an
189/// [`Option`](::core::option::Option) of a element, stopping when the first
190/// [`None`](::core::option::Option) is encountered.
191///
192/// Generates a new sized array generated from generator closure, which turns a index into a
193/// [`Option<T>`](::core::option::Option) with `T` being elements of the generated array. If a
194/// [`None`] value is found, the rest of the output array is filled with the `fill` value. Along
195/// with the generated array, this utility returns at what index the given
196/// [`None`](::core::option::Option) value was found
197/// (`OUTPUT_SIZE` if not found).
198///
199/// # Examples
200///
201/// ```
202/// use array_utils::initialize_from_option;
203/// assert_eq!(
204///     initialize_from_option(|index| if index == 5 { None } else { Some(index) }, 42),
205///     ([0, 1, 2, 3, 4, 42, 42, 42], 5)
206/// );
207/// ```
208///
209/// # Panics
210///
211/// Only panics if the given `f` panics.
212#[cfg(feature = "initialize")]
213pub fn initialize_from_option<T, F, const OUTPUT_SIZE: usize>(
214    f: F,
215    fill: T,
216) -> ([T; OUTPUT_SIZE], usize)
217where
218    T: Copy,
219    F: Fn(usize) -> Option<T>,
220{
221    let mut buffer = [fill; OUTPUT_SIZE];
222    for i in 0..OUTPUT_SIZE {
223        match f(i) {
224            None => return (buffer, i),
225            Some(value) => buffer[i] = value,
226        }
227    }
228    (buffer, OUTPUT_SIZE)
229}
230
231/// Initialize a sized array from a closure taking the index and outputting an
232/// [`Result`](::core::result::Result) of a element, stopping when the first
233/// [`Err`](::core::result::Result) is encountered.
234///
235/// Generates a new sized array generated from generator closure, which turns a index into a
236/// [`Result<T, E>`](::core::result::Result) with `T` being elements of the generated array. If a
237/// [`Err`] value is found, the rest of the output array is filled with the `fill` value. Along
238/// with the generated array, this utility returns at what index the given
239/// [`Err`](::core::result::Result) value was found
240/// (`OUTPUT_SIZE` if not found).
241///
242/// # Examples
243///
244/// ```
245/// use array_utils::initialize_from_result;
246/// assert_eq!(
247///     initialize_from_result(|index| if index == 5 { Err(()) } else { Ok(index) }, 42),
248///     ([0, 1, 2, 3, 4, 42, 42, 42], 5)
249/// );
250/// ```
251///
252/// # Panics
253///
254/// Only panics if the given `f` panics.
255#[cfg(feature = "initialize")]
256pub fn initialize_from_result<T, F, E, const OUTPUT_SIZE: usize>(
257    f: F,
258    fill: T,
259) -> ([T; OUTPUT_SIZE], usize)
260where
261    T: Copy,
262    F: Fn(usize) -> Result<T, E>,
263{
264    let mut buffer = [fill; OUTPUT_SIZE];
265    for i in 0..OUTPUT_SIZE {
266        match f(i) {
267            Err(_) => return (buffer, i),
268            Ok(value) => buffer[i] = value,
269        }
270    }
271    (buffer, OUTPUT_SIZE)
272}
273
274/// Create an array containing a slice of original array at the end of the array.
275///
276/// Floats a part of sized `array` with the range `..till` to the end of the result array
277/// with `margin` elements after the slice. All elements (including the margin) not filled with
278/// the slice will be filled with the `fill` value.
279///
280/// # Examples
281///
282/// ```
283/// use array_utils::drift_to_end;
284///
285/// // Float the elements with indices `..3` to the end with a margin of `0` elements,
286/// // filling in `42` for all new elements.
287/// assert_eq!(drift_to_end([1, 2, 3, 0, 0, 0, 0], 3, 0, 42), [42, 42, 42, 42, 1, 2, 3]);
288/// ```
289///
290/// # Notes
291///
292/// * If `till` is equal to `0` the resulting buffer will be `[fill; SIZE]`.
293/// * If `margin` is greater or equal to `SIZE` the resulting buffer will be `[fill; SIZE]`.
294#[cfg(feature = "drift")]
295pub fn drift_to_end<T, const SIZE: usize>(
296    array: [T; SIZE],
297    till: usize,
298    margin: usize,
299    fill: T,
300) -> [T; SIZE]
301where
302    T: Copy,
303{
304    let mut buffer = [fill; SIZE];
305    for i in 0..till {
306        buffer[SIZE - margin - till + i] = array[i];
307    }
308    buffer
309}
310
311/// Create an array containing a slice of original array at the beginning of the array.
312///
313/// Floats a part of sized `array` with the range `from..` to the beginning of the result array
314/// with `margin` elements before the slice. All elements (including the margin) not filled with
315/// the slice will be filled with the `fill` value.
316///
317/// # Examples
318///
319/// ```
320/// use array_utils::drift_to_begin;
321///
322/// // Float the elements with indices `0..` to the beginning with a margin of `1` elements,
323/// // filling in `0x00` for all new elements.
324/// assert_eq!(drift_to_begin([1, 2, 3, 0, 0, 0, 0], 0, 1, 0x00), [0, 1, 2, 3, 0, 0, 0]);
325/// ```
326///
327/// # Notes
328///
329/// * If `till` is equal to `0` the resulting buffer will be `[fill; SIZE]`.
330/// * If `margin` is greater or equal to `SIZE` the resulting buffer will be `[fill; SIZE]`.
331#[cfg(feature = "drift")]
332pub fn drift_to_begin<T, const SIZE: usize>(
333    array: [T; SIZE],
334    from: usize,
335    margin: usize,
336    fill: T,
337) -> [T; SIZE]
338where
339    T: Copy,
340{
341    let mut buffer = [fill; SIZE];
342    for i in from..SIZE {
343        if margin + i - from >= SIZE {
344            break;
345        }
346
347        buffer[margin + i - from] = array[i];
348    }
349    buffer
350}
351
352/// Resize a sized array to a different size.
353///
354/// Copy over the element from `array` into the resulting array. Truncating the original array or
355/// filling unfilled elements the `fill` value.
356///
357/// # Examples
358///
359/// ```
360/// use array_utils::array_resize;
361///
362/// // Truncating unnecessary values
363/// assert_eq!(array_resize([1, 2, 3], 0), [1, 2]);
364///
365/// // Inserting the `fill` value
366/// assert_eq!(array_resize([1, 2, 3], 0), [1, 2, 3, 0]);
367/// ```
368#[cfg(feature = "resize")]
369pub fn array_resize<T, const INPUT_SIZE: usize, const OUTPUT_SIZE: usize>(
370    array: [T; INPUT_SIZE],
371    fill: T,
372) -> [T; OUTPUT_SIZE]
373where
374    T: Copy,
375{
376    let mut buffer = [fill; OUTPUT_SIZE];
377    for i in 0..min_of_sizes(INPUT_SIZE, OUTPUT_SIZE) {
378        buffer[i] = array[i];
379    }
380    buffer
381}
382
383/// Superimpose an sized `sub_array` upon another `main_array` at index `starting_from`.
384///
385/// Create a copy of the `main_array` and insert all elements of `sub_array` into it,
386/// starting from the `starting_from` index. If the `sub_array` has more elements than fit in the
387/// `main_array` they are ignored.
388///
389/// # Examples
390///
391/// ```
392/// use array_utils::superimpose;
393///
394/// assert_eq!(
395///     superimpose([0; 8], [1, 3, 3, 7], 2),
396///     [0, 0, 1, 3, 3, 7, 0, 0]
397/// );
398///
399/// // Elements that don't fit in the main array size are ignored.
400/// assert_eq!(
401///     superimpose([1, 2, 3], [4, 2], 2),
402///     [1, 2, 4]
403/// );
404/// ```
405#[cfg(feature = "superimpose")]
406pub fn superimpose<T, const MAIN_SIZE: usize, const SUB_SIZE: usize>(
407    mut main_array: [T; MAIN_SIZE],
408    sub_array: [T; SUB_SIZE],
409    starting_from: usize,
410) -> [T; MAIN_SIZE]
411where
412    T: Copy,
413{
414    for i in starting_from..min_of_sizes(starting_from + SUB_SIZE, MAIN_SIZE) {
415        main_array[i] = sub_array[i - starting_from];
416    }
417    main_array
418}
419
420/// Join two sized arrays together into a new array.
421///
422/// Create a sized array which contain all the elements of `left` and `right` back to back. If
423/// there are any elements left to fill, they are filled up with the `fill` value. Any values of
424/// `left` or `right` that don't fit in the given buffer are ignored.
425///
426/// # Examples
427///
428/// ```
429/// use array_utils::join;
430///
431/// assert_eq!(join([1, 2, 3], [4, 5, 6], 0), [1, 2, 3, 4, 5, 6]);
432///
433/// // Leftover elements are filled up
434/// assert_eq!(join([1, 2, 3], [4, 5, 6], 0), [1, 2, 3, 4, 5, 6, 0, 0]);
435///
436/// // The input arrays are truncated if the resulting array is too short.
437/// assert_eq!(join([1, 2, 3], [4, 5, 6], 0), [1, 2, 3, 4, 5]);
438/// ```
439#[cfg(feature = "join")]
440pub fn join<T, const LEFT_SIZE: usize, const RIGHT_SIZE: usize, const RESULT_SIZE: usize>(
441    left: [T; LEFT_SIZE],
442    right: [T; RIGHT_SIZE],
443    fill: T,
444) -> [T; RESULT_SIZE]
445where
446    T: Copy,
447{
448    let mut buffer = [fill; RESULT_SIZE];
449
450    for i in 0..min_of_sizes(LEFT_SIZE, RESULT_SIZE) {
451        buffer[i] = left[i];
452    }
453
454    for i in LEFT_SIZE..min_of_sizes(LEFT_SIZE + RIGHT_SIZE, RESULT_SIZE) {
455        if i - LEFT_SIZE >= RIGHT_SIZE {
456            break;
457        }
458
459        buffer[i] = right[i - LEFT_SIZE];
460    }
461
462    buffer
463}
464
465/// Splice a sized arrays together into a two arrays.
466///
467/// Create two arrays the left being filled up first, then the right. If the given `original`
468/// array is two small to fill both buffers, the `fill` value is used for the remaining elements.
469///
470/// # Examples
471///
472/// ```
473/// use array_utils::splice;
474///
475/// assert_eq!(splice([1, 2, 3, 4, 5, 6], 0), ([1, 2, 3], [4, 5, 6]));
476///
477/// // Leftover elements are not used
478/// assert_eq!(splice([1, 2, 3, 4, 5, 6, 0, 0], 0), ([1, 2, 3], [4, 5, 6]));
479///
480/// // If the `original` buffer is to small the remaining elements are filled in.
481/// assert_eq!(splice([1, 2, 3, 4, 5], 0), ([1, 2, 3], [4, 5, 0]));
482/// ```
483#[cfg(feature = "splice")]
484pub fn splice<T, const ORIGINAL_SIZE: usize, const LEFT_SIZE: usize, const RIGHT_SIZE: usize>(
485    original: [T; ORIGINAL_SIZE],
486    fill: T,
487) -> ([T; LEFT_SIZE], [T; RIGHT_SIZE])
488where
489    T: Copy,
490{
491    let mut left = [fill; LEFT_SIZE];
492    let mut right = [fill; RIGHT_SIZE];
493
494    for i in 0..min_of_sizes(LEFT_SIZE, ORIGINAL_SIZE) {
495        left[i] = original[i];
496    }
497
498    for i in LEFT_SIZE..min_of_sizes(LEFT_SIZE + RIGHT_SIZE, ORIGINAL_SIZE) {
499        if i - LEFT_SIZE >= RIGHT_SIZE {
500            break;
501        }
502
503        right[i - LEFT_SIZE] = original[i];
504    }
505
506    (left, right)
507}
508
509/// Create a sized slice of an array.
510///
511/// Create a copy a part of sized array `original` from the index `from` till the index `till`.
512/// Filling the elements which are are contained in the `original` array with the `fill` value.
513///
514/// # Examples
515///
516/// ```
517/// use array_utils::sized_slice;
518///
519/// assert_eq!(sized_slice([1, 2, 3, 4, 5, 6, 7, 8, 9], 2, 6, 0), [3, 4, 5, 6]);
520/// assert_eq!(sized_slice([1, 2, 3, 4, 5, 6, 7, 8, 9], 6, 8, 0), [7, 8, 0, 0, 0, 0]);
521/// ```
522#[cfg(feature = "slice")]
523pub fn sized_slice<T, const ORIGINAL_SIZE: usize, const SLICE_SIZE: usize>(
524    original: [T; ORIGINAL_SIZE],
525    from: usize,
526    till: usize,
527    fill: T,
528) -> [T; SLICE_SIZE]
529where
530    T: Copy,
531{
532    let mut buffer = [fill; SLICE_SIZE];
533
534    for i in from..min_of_sizes(till, ORIGINAL_SIZE) {
535        if i - from >= SLICE_SIZE {
536            break;
537        }
538
539        buffer[i - from] = original[i];
540    }
541    buffer
542}
543
544#[cfg(test)]
545mod tests {
546    use super::*;
547
548    #[test]
549    #[cfg(feature = "initialize")]
550    fn init_from() {
551        assert_eq!(initialize_from(|index| index), []);
552        assert_eq!(initialize_from(|index| index), [0, 1, 2, 3, 4]);
553        assert_eq!(initialize_from(|index| 2 * index), [0, 2, 4, 6, 8]);
554        assert_eq!(initialize_from(|_| 1), [1; 20]);
555        assert_eq!(initialize_from(|index| 5 + index), [5, 6, 7, 8, 9, 10]);
556    }
557
558    #[test]
559    #[cfg(feature = "initialize")]
560    fn init_till() {
561        assert_eq!(
562            initialize_till(|index| index, 4, 42),
563            ([0, 1, 2, 3, 42, 42], 4)
564        );
565        assert_eq!(initialize_till(|index| index, 5, 42), ([0, 1, 2, 3, 4], 5));
566        assert_eq!(
567            initialize_till(|index| 2 * index, 8, 42),
568            ([0, 2, 4, 6, 42], 4)
569        );
570        assert_eq!(initialize_till(|_| 1, 3, 42), ([1; 20], 20));
571        assert_eq!(
572            initialize_till(|index| 5 + index, 20, 42),
573            ([5, 6, 7, 8, 9, 10], 6)
574        );
575    }
576
577    #[test]
578    #[cfg(feature = "initialize")]
579    fn init_from_option() {
580        assert_eq!(
581            initialize_from_option(|index| if index == 10 { None } else { Some(index) }, 42),
582            ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10)
583        );
584        assert_eq!(
585            initialize_from_option(|index| if index == 10 { None } else { Some(index) }, 42),
586            ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42, 42, 42, 42], 10)
587        );
588        assert_eq!(
589            initialize_from_option(|index| if index > 4 { None } else { Some(index) }, 42),
590            ([0, 1, 2, 3, 4, 42, 42, 42, 42], 5)
591        );
592    }
593
594    #[test]
595    #[cfg(feature = "initialize")]
596    fn init_from_result() {
597        assert_eq!(
598            initialize_from_result(|index| if index == 10 { Err(()) } else { Ok(index) }, 42),
599            ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10)
600        );
601        assert_eq!(
602            initialize_from_result(|index| if index == 10 { Err(()) } else { Ok(index) }, 42),
603            ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42, 42, 42, 42], 10)
604        );
605        assert_eq!(
606            initialize_from_result(|index| if index > 4 { Err(()) } else { Ok(index) }, 42),
607            ([0, 1, 2, 3, 4, 42, 42, 42, 42], 5)
608        );
609    }
610
611    #[test]
612    #[cfg(feature = "drift")]
613    fn drift_st() {
614        assert_eq!(
615            drift_to_begin(initialize_from(|index| index), 10, 2, 42),
616            superimpose([42; 13], [10, 11, 12], 2)
617        );
618        assert_eq!(
619            drift_to_begin(initialize_from(|index| index), 10, 0, 42),
620            superimpose([42; 13], [10, 11, 12], 0)
621        );
622        assert_eq!(
623            drift_to_begin(initialize_from(|index| index), 10, 1, 42),
624            superimpose([42; 13], [10, 11, 12], 1)
625        );
626    }
627
628    #[test]
629    #[cfg(feature = "drift")]
630    fn drift_nd() {
631        assert_eq!(
632            drift_to_end(initialize_from(|index| index), 3, 2, 42),
633            [42, 42, 0, 1, 2, 42, 42]
634        );
635        assert_eq!(
636            drift_to_end(initialize_from(|index| index), 3, 0, 42),
637            [42, 42, 0, 1, 2]
638        );
639        assert_eq!(
640            drift_to_end(initialize_from(|index| index), 3, 1, 42),
641            [0, 1, 2, 42]
642        );
643    }
644
645    #[test]
646    #[cfg(feature = "resize")]
647    fn arr_resize() {
648        let array: [usize; 10] = initialize_from(|index| index);
649        assert_eq!(array_resize(array, 42), [0, 1, 2, 3, 4, 5, 6, 7]);
650        assert_eq!(
651            array_resize(array, 42),
652            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42, 42]
653        );
654    }
655
656    #[test]
657    #[cfg(feature = "superimpose")]
658    fn super_impose() {
659        let array: [usize; 10] = initialize_from(|index| index);
660
661        assert_eq!(
662            superimpose(array, [0, 1, 2, 3], 4),
663            [0, 1, 2, 3, 0, 1, 2, 3, 8, 9]
664        );
665        assert_eq!(
666            superimpose(array, [0, 1, 2, 3], 8),
667            [0, 1, 2, 3, 4, 5, 6, 7, 0, 1]
668        );
669        assert_eq!(superimpose(array, [0, 1, 2, 3], 10), array);
670        assert_eq!(superimpose(array, [0, 1, 2, 3], 0), array);
671    }
672
673    #[test]
674    #[cfg(feature = "join")]
675    fn join_arrays() {
676        assert_eq!(
677            join([4, 5, 6, 7], [0, 1, 2, 3], 0),
678            [4, 5, 6, 7, 0, 1, 2, 3]
679        );
680        assert_eq!(
681            join([4, 5, 6, 7, 8], [0, 1, 2, 3], 0),
682            [4, 5, 6, 7, 8, 0, 1, 2, 3]
683        );
684        assert_eq!(
685            join([4, 5, 6, 7], [0, 1, 2, 3], 0),
686            [4, 5, 6, 7, 0, 1, 2, 3, 0]
687        );
688    }
689
690    #[test]
691    #[cfg(feature = "splice")]
692    fn splice_arrays() {
693        assert_eq!(
694            splice([4, 5, 6, 7, 0, 1, 2, 3], 0),
695            ([4, 5, 6, 7], [0, 1, 2, 3])
696        );
697        assert_eq!(
698            splice([4, 5, 6, 7, 8, 0, 1, 2, 3], 0),
699            ([4, 5, 6, 7, 8], [0, 1, 2, 3])
700        );
701        assert_eq!(
702            splice([4, 5, 6, 7, 0, 1, 2, 3, 0], 0),
703            ([4, 5, 6, 7], [0, 1, 2, 3])
704        );
705        assert_eq!(
706            splice([4, 5, 6, 7, 0, 1, 2, 3, 0], 0),
707            ([4, 5, 6, 7], [0, 1, 2, 3, 0, 0, 0, 0])
708        );
709    }
710
711    #[test]
712    #[cfg(feature = "slice")]
713    fn sized_slices() {
714        assert_eq!(
715            sized_slice([4, 5, 6, 7, 0, 1, 2, 3], 4, 8, 0),
716            ([0, 1, 2, 3])
717        );
718        assert_eq!(
719            sized_slice([4, 5, 6, 7, 0, 1, 2, 3], 4, 10, 0),
720            ([0, 1, 2, 3, 0, 0])
721        );
722        assert_eq!(
723            sized_slice([4, 5, 6, 7, 0, 1, 2, 3], 0, 10, 0),
724            ([4, 5, 6, 7, 0, 1])
725        );
726    }
727}