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