1pub(crate) const MAX_DEPTH: usize = 20;
5
6#[inline]
16#[deprecated(note = "use `try_recursion_guard` instead")]
17pub fn recursion_guard(
18 depth: usize,
19 f: impl FnOnce(usize) -> (usize, Option<usize>),
20) -> (usize, Option<usize>) {
21 if depth > MAX_DEPTH {
22 (0, None)
23 } else {
24 f(depth + 1)
25 }
26}
27
28#[inline]
38pub fn try_recursion_guard(
39 depth: usize,
40 f: impl FnOnce(usize) -> Result<(usize, Option<usize>), crate::MaxRecursionReached>,
41) -> Result<(usize, Option<usize>), crate::MaxRecursionReached> {
42 if depth > MAX_DEPTH {
43 Err(crate::MaxRecursionReached {})
44 } else {
45 f(depth + 1)
46 }
47}
48
49#[inline]
51pub fn and(lhs: (usize, Option<usize>), rhs: (usize, Option<usize>)) -> (usize, Option<usize>) {
52 let lower = lhs.0 + rhs.0;
53 let upper = lhs.1.and_then(|lhs| rhs.1.map(|rhs| lhs + rhs));
54 (lower, upper)
55}
56
57#[inline]
62pub fn and_all(hints: &[(usize, Option<usize>)]) -> (usize, Option<usize>) {
63 hints.iter().copied().fold((0, Some(0)), and)
64}
65
66#[inline]
69pub fn or(lhs: (usize, Option<usize>), rhs: (usize, Option<usize>)) -> (usize, Option<usize>) {
70 let lower = std::cmp::min(lhs.0, rhs.0);
71 let upper = lhs
72 .1
73 .and_then(|lhs| rhs.1.map(|rhs| std::cmp::max(lhs, rhs)));
74 (lower, upper)
75}
76
77#[inline]
82pub fn or_all(hints: &[(usize, Option<usize>)]) -> (usize, Option<usize>) {
83 if let Some(head) = hints.first().copied() {
84 hints[1..].iter().copied().fold(head, or)
85 } else {
86 (0, Some(0))
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 #[test]
93 fn and() {
94 assert_eq!((5, Some(5)), super::and((2, Some(2)), (3, Some(3))));
95 assert_eq!((5, None), super::and((2, Some(2)), (3, None)));
96 assert_eq!((5, None), super::and((2, None), (3, Some(3))));
97 assert_eq!((5, None), super::and((2, None), (3, None)));
98 }
99
100 #[test]
101 fn or() {
102 assert_eq!((2, Some(3)), super::or((2, Some(2)), (3, Some(3))));
103 assert_eq!((2, None), super::or((2, Some(2)), (3, None)));
104 assert_eq!((2, None), super::or((2, None), (3, Some(3))));
105 assert_eq!((2, None), super::or((2, None), (3, None)));
106 }
107
108 #[test]
109 fn and_all() {
110 assert_eq!((0, Some(0)), super::and_all(&[]));
111 assert_eq!(
112 (7, Some(7)),
113 super::and_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))])
114 );
115 assert_eq!(
116 (7, None),
117 super::and_all(&[(1, Some(1)), (2, Some(2)), (4, None)])
118 );
119 assert_eq!(
120 (7, None),
121 super::and_all(&[(1, Some(1)), (2, None), (4, Some(4))])
122 );
123 assert_eq!(
124 (7, None),
125 super::and_all(&[(1, None), (2, Some(2)), (4, Some(4))])
126 );
127 }
128
129 #[test]
130 fn or_all() {
131 assert_eq!((0, Some(0)), super::or_all(&[]));
132 assert_eq!(
133 (1, Some(4)),
134 super::or_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))])
135 );
136 assert_eq!(
137 (1, None),
138 super::or_all(&[(1, Some(1)), (2, Some(2)), (4, None)])
139 );
140 assert_eq!(
141 (1, None),
142 super::or_all(&[(1, Some(1)), (2, None), (4, Some(4))])
143 );
144 assert_eq!(
145 (1, None),
146 super::or_all(&[(1, None), (2, Some(2)), (4, Some(4))])
147 );
148 }
149}