1#[inline]
3#[doc(hidden)]
4pub const fn __array_uninit<T, const N: usize>() -> [::core::mem::MaybeUninit<T>; N] {
5 [const { ::core::mem::MaybeUninit::uninit() }; N] }
7
8#[inline]
10#[doc(hidden)]
11pub const unsafe fn __array_assume_init<T, const N: usize>(
12 array: [::core::mem::MaybeUninit<T>; N],
13) -> [T; N] {
14 unsafe { ::core::mem::transmute_copy(&array) }
16}
17
18#[inline]
20#[doc(hidden)]
21pub const fn __manually_drop_inner_ref<T>(slot: &::core::mem::ManuallyDrop<T>) -> &T {
22 unsafe { ::core::mem::transmute(slot) }
24}
25
26#[inline]
28#[doc(hidden)]
29pub const fn __same_len<A, B, const N: usize>(_: &[A; N], _: &[B; N]) {}
30
31#[doc(hidden)]
33#[macro_export]
34macro_rules! __same_len {
35 ($a:expr, $($rest:tt)*) => {{
36 $crate::__same_len!(@impl $a, $($rest)*);
37 $a.len()
38 }};
39 (@impl $a:expr, $b:expr $(,)?) => {
40 $crate::__same_len($a, $b);
41 };
42 (@impl $a:expr, $b:expr, $($rest:tt)*) => {
43 $crate::__same_len($a, $b);
44 $crate::__same_len!(@impl $b, $($rest)*);
45 };
46}
47
48#[macro_export]
49macro_rules! const_map_array {
50 (let ($($oa_pat:pat_param),+ $(,)?) = $($rest:tt)*) => {
51 $crate::const_map_array!(@zip_outputs (($($oa_pat),*) ((o0a, o0), (o1a, o1), (o2a, o2), (o3a, o3), (o4a, o4), (o5a, o5), (o6a, o6), (o7a, o7), (o8a, o8), (o9a, o9), (o10a, o10), (o11a, o11)) => ()) ($($rest)*) => (multi_output) );
52 };
53 (let $oa_pat:pat_param = $($rest:tt)*) => {
54 $crate::const_map_array!(@zip_outputs (($oa_pat) ((o0a, o0)) => ()) ($($rest)*) => (single_output) );
55 };
56 (@zip_outputs (() ($($_:tt),*) => ($($arg:tt)*)) ($($rest:tt)*) => $($args:tt)*) => {
57 $crate::const_map_array!(@parse_inputs ($($rest)*) => $($args)* ($($arg)*));
58 };
59 (@zip_outputs (($($oa_pat:pat_param),+) () => ($($arg:tt)*)) ($($rest:tt)*) => $($args:tt)*) => {
60 compile_error!("const_map_array only supports up to 12 outputs");
61 };
62 (@zip_outputs (($oa_pat_head:pat_param $(,$oa_pat_tail:pat_param)*) (($oa_head:ident, $o_head:ident) $(,($oa_tail:ident, $o_tail:ident))*) => ($(($oa_pat:pat_param, $oa:ident, $o:ident)),*)) ($($rest:tt)*) => $($args:tt)*) => {
63 $crate::const_map_array!(@zip_outputs (($($oa_pat_tail),*) ($(($oa_tail, $o_tail)),*) => ($(($oa_pat, $oa, $o),)* ($oa_pat_head, $oa_head, $o_head))) ($($rest)*) => $($args)*);
64 };
65 (@parse_inputs (map($ia_expr:expr, |($($i_pat:pat_param),+ $(,)?)| $body:expr)) => $($args:tt)*) => {
66 $crate::const_map_array!(@zip_inputs (($($i_pat),*) ((i0, i0a), (i1, i1a), (i2, i2a), (i3, i3a), (i4, i4a), (i5, i5a), (i6, i6a), (i7, i7a), (i8, i8a), (i9, i9a), (i10, i10a), (i11, i11a)) => ()) => $($args)* (multi_input) ($ia_expr) ($body));
67 };
68 (@parse_inputs (map($ia_expr:expr, |$i_pat:pat_param| $body:expr)) => $($args:tt)*) => {
69 $crate::const_map_array!(@zip_inputs (($i_pat) ((i0, i0a)) => ()) => $($args)* (single_input) ($ia_expr) ($body));
70 };
71 (@zip_inputs (() ($($_:tt),*) => ($($arg:tt)*)) => $($args:tt)*) => {
72 $crate::const_map_array!(@call $($args)* ($($arg)*));
73 };
74 (@zip_inputs (($($i_pat:pat_param),+) () => ($($arg:tt)*)) => $($args:tt)*) => {
75 compile_error!("const_map_array only supports up to 12 inputs");
76 };
77 (@zip_inputs (($i_pat_head:pat_param $(,$i_pat_tail:pat_param)*) (($i_head:ident, $ia_head:ident) $(,($i_tail:ident, $ia_tail:ident))*) => ($(($i_pat:pat_param, $i:ident, $ia:ident)),*)) => $($args:tt)*) => {
78 $crate::const_map_array!(@zip_inputs (($($i_pat_tail),*) ($(($i_tail, $ia_tail)),*) => ($(($i_pat, $i, $ia),)* ($i_pat_head, $i_head, $ia_head))) => $($args)*);
79 };
80 (@call ($output:tt) ($(($oa_pat:pat_param, $oa:ident, $o:ident)),*) ($input:tt) ($ia_expr:expr) ($body:expr) ($(($i_pat:pat_param, $i:ident, $ia:ident)),*)) => {
81 $(
82 let mut $oa = $crate::__array_uninit();
83 )*
84
85 $crate::const_map_array!(@destructure_input $input ($ia_expr) ($($ia),*));
86 $(
87 let $ia = ::core::mem::ManuallyDrop::<[_; _]>::new($ia);
88 let $ia = $crate::__manually_drop_inner_ref(&$ia);
89 )*
90
91 let end = $crate::__same_len!($(&$oa,)* $(&$ia),*);
92 let mut index = 0;
93 #[allow(unreachable_code)] while index < end {
95 $(
96 let $i_pat = unsafe { ::core::ptr::addr_of!($ia[index]).read() };
97 )*
98
99 let item = $body;
100 $crate::const_map_array!(@write_outputs $output ($(($oa, $o)),*) (index) (item));
101 index += 1;
102 };
103
104 assert!(index == end, "break is not allowed because a value must be written into every array element");
105
106 $(
107 let $oa_pat = unsafe { $crate::__array_assume_init($oa) };
108 )*
109 };
110 (@destructure_input single_input ($ia_expr:expr) ($ia:ident)) => {
111 let $ia = $ia_expr;
112 };
113 (@destructure_input multi_input ($ia_expr:expr) ($($ia:ident),*)) => {
114 ::const_destructure::const_destructure!(let ($($ia),*) = $ia_expr);
115 };
116 (@write_outputs single_output (($oa:ident, $o:ident)) ($index:ident) ($item:ident)) => {
118 $oa[$index].write($item);
119 };
120 (@write_outputs multi_output ($(($oa:ident, $o:ident)),*) ($index:ident) ($item:ident)) => {
121 ::const_destructure::const_destructure!(let ($($o),*) = $item);
122 $(
123 $oa[$index].write($o);
124 )*
125 };
126}