1use std::convert::Infallible;
19use std::error::Error;
20
21use seq_macro::seq;
22
23macro_rules! repeat {
24 ($counter:ident to $upto:expr => $body:block) => {
25 <crate::repeat::Count<$upto> as crate::repeat::Repeat>::repeat(
26 #[inline(always)]
27 |$counter| $body,
28 );
29 };
30 ($counter:ident to $upto:expr ; while $cond:expr => $body:block) => {
31 <crate::repeat::Count<$upto> as crate::repeat::Repeat>::repeat_while(
32 #[inline(always)]
33 |$counter| $cond,
34 #[inline(always)]
35 |$counter| $body,
36 )
37 };
38}
39pub(crate) use repeat;
40
41macro_rules! try_repeat {
42 ($counter:ident to $upto:expr ; while $cond:expr => $body:block) => {
43 <crate::repeat::Count<$upto> as crate::repeat::Repeat>::try_repeat_while(
44 #[inline(always)]
45 |$counter| $cond,
46 #[inline(always)]
47 |$counter| $body,
48 )
49 };
50}
51pub(crate) use try_repeat;
52
53pub trait Repeat {
55 #[allow(clippy::inline_always)]
56 #[inline(always)]
57 fn repeat<F: FnMut(usize)>(body_fn: F) {
58 Self::repeat_while(
59 #[inline(always)]
60 |_n| true,
61 body_fn,
62 );
63 }
64 #[allow(clippy::inline_always)]
65 #[inline(always)]
66 fn repeat_while<F: FnMut(usize), C: FnMut(usize) -> bool>(cond_fn: C, mut body_fn: F) {
67 Self::try_repeat_while::<Infallible, _, _>(
68 cond_fn,
69 #[inline(always)]
70 |n| {
71 body_fn(n);
72 Ok(())
73 },
74 )
75 .unwrap();
76 }
77 fn try_repeat_while<E: Error, F: FnMut(usize) -> Result<(), E>, C: FnMut(usize) -> bool>(
78 cond_fn: C,
79 body_fn: F,
80 ) -> Result<(), E>;
81}
82
83pub struct Count<const N: usize>;
84
85seq!(M in 1..=32 {
86
87 impl Repeat for Count<M> {
88 #[allow(clippy::inline_always)]
89 #[inline(always)]
90 fn try_repeat_while<E: Error, F: FnMut(usize) -> Result<(), E>, C: FnMut(usize) -> bool>(mut cond_fn: C, mut body_fn: F) -> Result<(), E> {
91 seq!(T in 0..M {
92 if !cond_fn(T) {
93 return Ok(())
94 }
95 body_fn(T)?;
96 });
97 Ok(())
98 }
99 }
100
101});