1#![no_std]
2
3#[macro_export]
18macro_rules! auto_array {
19 ($($(#[$attr:meta])* $vis:vis $const_or_static:ident $name:ident: [$ty:ty; _] = $array:expr;)*) => {
20 $($(#[$attr])* $vis $const_or_static $name: [$ty; <[$ty]>::len(<[$ty; _]>::as_slice(&$array))] = $array;)*
21 };
22}
23
24#[cfg(test)]
25mod tests {
26 macro_rules! assert_type_and_value {
27 ($($lhs:path: $ty:ty = $rhs:expr;)*) => {
28 $(let _: $ty = $lhs;
29 assert_eq!($lhs, $rhs);)*
30 };
31 }
32
33 #[test]
34 fn single_arrays() {
35 auto_array!(
36 pub const A: [i32; _] = [1, 2, 3];
37 );
38 auto_array!(
39 pub(super) static B: [i8; _] = [4, 4, 4, 4];
40 );
41 assert_type_and_value!(
42 A: [i32; 3] = [1, 2, 3];
43 B: [i8; 4] = [4, 4, 4, 4];
44 );
45 }
46
47 #[test]
48 fn multiple_arrays() {
49 auto_array!(
50 const A: [i8; _] = [1, 2, 3];
51 const B: [i16; _] = [];
52 const C: [i32; _] = [4, 4, 4, 4];
53 const D: [i64; _] = [6, 6, 6, 6, 6, 6];
54 );
55 assert_type_and_value!(
56 A: [i8; 3] = [1, 2, 3];
57 B: [i16; 0] = [];
58 C: [i32; 4] = [4, 4, 4, 4];
59 D: [i64; 6] = [6, 6, 6, 6, 6, 6];
60 );
61
62 auto_array!(
63 static E: [u32; _] = [1];
64 static F: [u64; _] = [2, 2];
65 );
66 assert_type_and_value!(
67 E: [u32; 1] = [1];
68 F: [u64; 2] = [2, 2];
69 );
70 }
71
72 #[test]
73 fn mix_const_and_static() {
74 auto_array!(
75 const A: [u8; _] = [2, 2];
76 static B: [u8; _] = [3, 3, 3];
77 );
78 assert_type_and_value!(
79 A: [u8; 2] = [2, 2];
80 B: [u8; 3] = [3, 3, 3];
81 );
82 }
83
84 #[test]
85 #[deny(dead_code, clippy::approx_constant)]
86 fn attributes() {
87 auto_array!(
88 #[expect(dead_code)]
89 #[expect(clippy::approx_constant)]
90 pub(crate) const UNUSED: [f32; _] = [3.14];
91 );
92 }
93
94 #[test]
95 fn empty_invocation() {
96 auto_array!();
97 }
98}