macro_rules! build {
(|$prefix:ident : &[$type:ty]| $item:expr $(; $len:expr)?) => { ... };
(|$index:ident : usize| $item:expr $(; $len:expr)?) => { ... };
($item:expr $(; $len:expr)?) => { ... };
}
Expand description
Build an array with an expression.
This macro builds an array by calling an expression once for each element in the array:
use brownstone::build;
let x: [String; 3] = build!["hello".to_owned()];
assert_eq!(x, ["hello", "hello", "hello"])
You can also provide an explicit length in the macro, if the length can’t be inferred from context:
use brownstone::build;
let x = build!["hello".to_owned(); 3];
assert_eq!(x, ["hello", "hello", "hello"]);
If needed, you can use a closure syntax (with a usize
parameter) to evaluate
your expression with the index of the item being evaluated:
use brownstone::build;
let x = build!(|index: usize| (index as i32) * 2; 4);
assert_eq!(x, [0, 2, 4, 6]);
You can also instead use an &[T]
parameter to to evaluate your expression with
the full prefix of the array that has already been built:
use brownstone::build;
let x = build!(|prefix: &[i32]| match prefix {
[.., a, b] => a + b,
_ => 1,
});
assert_eq!(x, [1, 1, 2, 3, 5, 8, 13]);
All of these forms (even the closure-style forms) are evaluated locally, which
means that you can use arbitrary* control flow inside the builder, such as ?
or return
or await
:
use std::{io, num};
use brownstone::build;
#[derive(Debug)]
enum Error {
Io(io::Error),
Parse(num::ParseIntError),
}
fn read_4_ints(mut input: impl io::BufRead) -> Result<[i32; 4], Error> {
let mut line = String::new();
let array = build!({
line.clear();
input.read_line(&mut line).map_err(Error::Io)?;
line.trim().parse().map_err(Error::Parse)?
});
Ok(array)
}
let data = b"12\n4\n6\n21\n5";
let data = read_4_ints(data.as_slice()).expect("failed to read or parse");
assert_eq!(data, [12, 4, 6, 21]);
* Currently it doesn’t support break
or continue
; this is a bug and
will be fixed in a future release.