1use crate::box_iter::{box_once, flat_map_with, map_with, then, BoxIter};
4use crate::val::{ValR, ValT, ValX, ValXs};
5use alloc::{boxed::Box, vec::Vec};
6
7#[derive(Clone, Debug)]
9pub struct Path<F>(pub Vec<(Part<F>, Opt)>);
10
11#[derive(Clone, Debug)]
13pub enum Part<I> {
14 Index(I),
16 Range(Option<I>, Option<I>),
19}
20
21#[derive(Copy, Clone, Debug)]
27pub enum Opt {
28 Optional,
30 Essential,
32}
33
34impl<I> Default for Part<I> {
35 fn default() -> Self {
36 Self::Range(None, None)
37 }
38}
39
40impl Opt {
41 pub fn fail<T, E>(self, x: T, f: impl FnOnce(T) -> E) -> Result<T, E> {
43 match self {
44 Self::Optional => Ok(x),
45 Self::Essential => Err(f(x)),
46 }
47 }
48}
49
50impl<'a, U: Clone + 'a, E: Clone + 'a, T: Clone + IntoIterator<Item = Result<U, E>> + 'a> Path<T> {
51 pub(crate) fn explode(self) -> impl Iterator<Item = Result<Path<U>, E>> + 'a {
52 Path(Vec::new())
53 .combinations(self.0.into_iter())
54 .map(Path::transpose)
55 }
56}
57
58impl<'a, U: Clone + 'a> Path<U> {
59 fn combinations<I, F>(self, mut iter: I) -> BoxIter<'a, Self>
60 where
61 I: Iterator<Item = (Part<F>, Opt)> + Clone + 'a,
62 F: IntoIterator<Item = U> + Clone + 'a,
63 {
64 if let Some((part, opt)) = iter.next() {
65 let parts = part.into_iter();
66 flat_map_with(parts, (self, iter), move |part, (mut prev, iter)| {
67 prev.0.push((part, opt));
68 prev.combinations(iter)
69 })
70 } else {
71 box_once(self)
72 }
73 }
74}
75
76impl<'a, V: ValT + 'a> Path<V> {
77 pub(crate) fn run(self, v: V) -> BoxIter<'a, ValR<V>> {
78 run(self.0.into_iter(), v)
79 }
80
81 pub(crate) fn update<F>(mut self, v: V, f: F) -> ValX<'a, V>
82 where
83 F: Fn(V) -> ValXs<'a, V>,
84 {
85 if let Some(last) = self.0.pop() {
86 update(self.0.into_iter(), last, v, &f)
87 } else {
88 Ok(v)
90 }
91 }
92}
93
94fn run<'a, V: ValT + 'a, I>(mut iter: I, val: V) -> BoxIter<'a, ValR<V>>
95where
96 I: Iterator<Item = (Part<V>, Opt)> + Clone + 'a,
97{
98 if let Some((part, opt)) = iter.next() {
99 let essential = matches!(opt, Opt::Essential);
100 let ys = part.run(val).filter(move |v| essential || v.is_ok());
101 flat_map_with(ys, iter, move |v, iter| then(v, |v| run(iter, v)))
102 } else {
103 box_once(Ok(val))
104 }
105}
106
107fn update<'a, V: ValT + 'a, P, F>(mut iter: P, last: (Part<V>, Opt), v: V, f: &F) -> ValX<'a, V>
108where
109 P: Iterator<Item = (Part<V>, Opt)> + Clone,
110 F: Fn(V) -> ValXs<'a, V>,
111{
112 if let Some((part, opt)) = iter.next() {
113 use core::iter::once;
114 part.update(v, opt, |v| once(update(iter.clone(), last.clone(), v, f)))
115 } else {
116 last.0.update(v, last.1, f)
117 }
118}
119
120impl<'a, V: ValT + 'a> Part<V> {
121 fn run(&self, v: V) -> impl Iterator<Item = ValR<V>> + 'a {
122 match self {
123 Self::Index(idx) => box_once(v.index(idx)),
124 Self::Range(None, None) => Box::new(v.values()),
125 Self::Range(from, upto) => box_once(v.range(from.as_ref()..upto.as_ref())),
126 }
127 }
128
129 fn update<F, I>(&self, v: V, opt: Opt, f: F) -> ValX<'a, V>
130 where
131 F: Fn(V) -> I,
132 I: Iterator<Item = ValX<'a, V>>,
133 {
134 match self {
135 Self::Index(idx) => v.map_index(idx, opt, f),
136 Self::Range(None, None) => v.map_values(opt, f),
137 Self::Range(from, upto) => v.map_range(from.as_ref()..upto.as_ref(), opt, f),
138 }
139 }
140}
141
142impl<'a, U: Clone + 'a, F: IntoIterator<Item = U> + Clone + 'a> Part<F> {
143 fn into_iter(self) -> BoxIter<'a, Part<U>> {
144 use Part::{Index, Range};
145 match self {
146 Index(i) => Box::new(i.into_iter().map(Index)),
147 Range(None, None) => box_once(Range(None, None)),
148 Range(Some(from), None) => {
149 Box::new(from.into_iter().map(|from| Range(Some(from), None)))
150 }
151 Range(None, Some(upto)) => {
152 Box::new(upto.into_iter().map(|upto| Range(None, Some(upto))))
153 }
154 Range(Some(from), Some(upto)) => {
155 Box::new(flat_map_with(from.into_iter(), upto, move |from, upto| {
156 map_with(upto.into_iter(), from, move |upto, from| {
157 Range(Some(from), Some(upto))
158 })
159 }))
160 }
161 }
162 }
163}
164
165impl<T> Path<T> {
166 pub(crate) fn map_ref<'a, U>(&'a self, mut f: impl FnMut(&'a T) -> U) -> Path<U> {
167 let path = self.0.iter();
168 let path = path.map(move |(part, opt)| (part.as_ref().map(&mut f), *opt));
169 Path(path.collect())
170 }
171}
172
173impl<T> Part<T> {
174 pub(crate) fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> Part<U> {
176 use Part::{Index, Range};
177 match self {
178 Index(i) => Index(f(i)),
179 Range(from, upto) => Range(from.map(&mut f), upto.map(&mut f)),
180 }
181 }
182}
183
184impl<T, E> Path<Result<T, E>> {
185 fn transpose(self) -> Result<Path<T>, E> {
186 self.0
187 .into_iter()
188 .map(|(part, opt)| Ok((part.transpose()?, opt)))
189 .collect::<Result<_, _>>()
190 .map(Path)
191 }
192}
193
194impl<T, E> Part<Result<T, E>> {
195 fn transpose(self) -> Result<Part<T>, E> {
196 match self {
197 Self::Index(i) => Ok(Part::Index(i?)),
198 Self::Range(from, upto) => Ok(Part::Range(from.transpose()?, upto.transpose()?)),
199 }
200 }
201}
202
203impl<F> Part<F> {
204 fn as_ref(&self) -> Part<&F> {
205 match self {
206 Self::Index(i) => Part::Index(i),
207 Self::Range(from, upto) => Part::Range(from.as_ref(), upto.as_ref()),
208 }
209 }
210}
211
212impl<F> From<Part<F>> for Path<F> {
213 fn from(p: Part<F>) -> Self {
214 Self(Vec::from([(p, Opt::Essential)]))
215 }
216}