1use crate::{Pipe, Result as PResult};
2use fatal_error::FatalError;
3use std::{
4 convert::Infallible,
5 marker::PhantomData,
6 ops::{
7 Bound, Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo,
8 RangeToInclusive,
9 },
10};
11use tuplify::Unpack;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct InvalidRepetition(usize, usize);
16
17impl From<Infallible> for InvalidRepetition {
18 fn from(_: Infallible) -> Self { unreachable!() }
19}
20
21impl std::fmt::Display for InvalidRepetition {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 write!(f, "Invalid repetition: min: {} - max: {}", self.0, self.1)
24 }
25}
26
27impl std::error::Error for InvalidRepetition {}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct Repetition {
34 min: usize,
35 max: Option<usize>,
36}
37
38impl Repetition {
39 pub fn range(min: usize, max: Option<usize>) -> Result<Self, InvalidRepetition> {
45 if max.map_or(true, |x| x >= min) {
46 Ok(Repetition { min, max })
47 } else {
48 Err(InvalidRepetition(min, max.unwrap()))
49 }
50 }
51
52 pub fn exact(n: usize) -> Result<Self, InvalidRepetition> {
54 Ok(Repetition { min: n, max: Some(n) })
55 }
56
57 pub fn needs_more(&self, nb: usize) -> bool { nb < self.min }
59
60 pub fn is_max(&self, nb: usize) -> bool { self.max.map_or(false, |x| nb == x) }
62
63 pub fn map_err<E>(
67 &self, nb: usize, f: impl FnOnce(usize, Option<usize>, usize) -> E,
68 ) -> Result<(), E> {
69 if nb >= self.min && self.max.map_or(true, |x| nb <= x) {
70 Ok(())
71 } else {
72 Err(f(self.min, self.max, nb))
73 }
74 }
75
76 pub fn min_needed(&self, nb: usize) -> usize { self.min.saturating_sub(nb) }
78}
79
80impl TryFrom<usize> for Repetition {
81 type Error = InvalidRepetition;
82
83 fn try_from(value: usize) -> Result<Self, Self::Error> { Self::exact(value) }
84}
85
86impl From<RangeFrom<usize>> for Repetition {
87 fn from(value: RangeFrom<usize>) -> Self {
88 Repetition { min: value.start, max: None }
89 }
90}
91
92impl From<RangeFull> for Repetition {
93 fn from(_: RangeFull) -> Self { Repetition { min: 0, max: None } }
94}
95
96impl TryFrom<Range<usize>> for Repetition {
97 type Error = InvalidRepetition;
98
99 fn try_from(value: Range<usize>) -> Result<Self, Self::Error> {
100 Repetition::range(
101 value.start,
102 match value.end_bound() {
103 Bound::Included(x) => Some(*x),
104 Bound::Excluded(x) => Some(x.saturating_sub(1)),
105 Bound::Unbounded => None,
106 },
107 )
108 }
109}
110
111impl TryFrom<RangeInclusive<usize>> for Repetition {
112 type Error = InvalidRepetition;
113
114 fn try_from(value: RangeInclusive<usize>) -> Result<Self, Self::Error> {
115 Repetition::range(*value.start(), Some(*value.end()))
116 }
117}
118
119impl TryFrom<RangeTo<usize>> for Repetition {
120 type Error = InvalidRepetition;
121
122 fn try_from(value: RangeTo<usize>) -> Result<Self, Self::Error> {
123 Repetition::range(0, Some(value.end.saturating_sub(1)))
124 }
125}
126
127impl TryFrom<RangeToInclusive<usize>> for Repetition {
128 type Error = InvalidRepetition;
129
130 fn try_from(value: RangeToInclusive<usize>) -> Result<Self, Self::Error> {
131 Repetition::range(0, Some(value.end))
132 }
133}
134
135pub trait RepeatExt<I, O, E> {
137 fn repeat<R>(self, r: R) -> RepeatPipe<Self, O>
141 where
142 R: TryInto<Repetition>,
143 R::Error: std::error::Error,
144 Self: Pipe<I, O, E> + Sized,
145 {
146 RepeatPipe::new(self, r.try_into().unwrap())
147 }
148}
149
150impl<I, O, E, P> RepeatExt<I, O, E> for P where P: Pipe<I, O, E> {}
151
152pub struct RepeatPipe<P, O> {
154 p: P,
155 r: Repetition,
156 o: PhantomData<O>,
157}
158
159impl<P, O> RepeatPipe<P, O> {
160 fn new(p: P, r: Repetition) -> Self { Self { p, r, o: PhantomData } }
161}
162
163impl<I, O, E, P> Pipe<I, (Vec<O::Output>,), E> for RepeatPipe<P, O>
164where
165 I: Clone,
166 O: Unpack,
167 P: Pipe<I, O, E> + Sized,
168{
169 fn apply(&mut self, mut input: I) -> PResult<I, (Vec<O::Output>,), E> {
170 let mut r = Vec::new();
171 for x in 0.. {
172 match self.p.apply(input.clone()) {
173 Ok((i, o)) => {
174 input = i;
175 r.push(o.unpack());
176 }
177 Err(e @ FatalError::Error(_)) => {
178 if self.r.needs_more(x) {
179 return Err(e);
180 } else {
181 break;
182 }
183 }
184 Err(x) => return Err(x),
185 }
186 if self.r.is_max(x) {
187 break;
188 }
189 }
190 Ok((input, (r,)))
191 }
192}