Utilities for working with uninitialized arrays
- No dependencies
#[no_std]
- No panics (all APIs return
Result
orOption
)
This crate provides a few sets of APIs:
These are a pair of functions which are generally used as follows:
- stack-allocate an uninitialized array with
uninit_buf
- initialize each element
- unsafely convert it to an initialized array with
mark_initialized
For example:
use unarray::*;
fn main() {
let mut buffer = uninit_buf::<i32; 10>();
for slot in &mut buffer {
slot.write(123);
}
let array = unsafe { mark_initialized(buffer) };
assert_eq!(array, [123; 10]);
}
This is simple to understand, but still requires unsafe
, which is hard to justify in many cases
Functions to build arrays from a length and a function that maps from index -> value:
let even_numbers = build_array(|i| i * 2); // const generic length parameter inferred
assert_eq!(even_numbers, [0, 2, 4]);
let numbers = build_array_option::<usize, 3>(|i| 3.checked_sub(i));
assert_eq!(numbers, Some([3, 2, 1]));
let numbers = build_array_option::<usize, 5>(|i| 3.checked_sub(i));
assert_eq!(numbers, None); // since a single element failed, the whole operation failed
There is also an equivalent build_array_result
for Result
-returning functions
It's fairly common to want to collect an iterator into an array, but this is currently tricky in
stable Rust, since iterators don't carry compile-time information about their length. Because of this,
arrays don't implement FromIterator
, which is required for .collect()
to work.
Instead, this library provides ArrayFromIter
, which does implement FromIterator
. This struct can
be destructured to get an Option<[T, N]>
. If the iterator contained exactly N
elements, this is Some(array)
, otherwise, it is None
:
let iter = [1, 2, 3].into_iter();
match iter.collect() {
ArrayFromIter(Some([a, b, c])) => println!("exactly 3 elements: {a}, {b}, {c}"),
ArrayFromIter(None) => println!("not 3 elements"),
}
// mapping an array via a `Result`
let strings = ["123", "234"];
let numbers = strings.map_result(|s| s.parse());
assert_eq!(numbers, Ok([123, 234]));
let bad_strings = ["123", "uh oh"];
let result = bad_strings.map_result(|s| s.parse::<i32>());
assert!(result.is_err()); // since one of the element fails, the whole operation fails
There is also map_option
for functions which return an Option
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.