1use crate::data::section::FallibleMap;
13#[cfg(feature = "map-adapter")]
14use crate::data::section::Map;
15use crate::data::storage::{Storage, VecStorage};
16use crate::mesh_error::MeshSieveError;
17use crate::topology::point::PointId;
18use crate::topology::sieve::Sieve;
19use core::marker::PhantomData;
20
21#[cfg(feature = "map-adapter")]
22#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
23pub fn restrict_closure<'s, M, V: 's>(
31 sieve: &'s impl Sieve<Point = PointId>,
32 map: &'s M,
33 seeds: impl IntoIterator<Item = PointId>,
34) -> impl Iterator<Item = (PointId, &'s [V])> + 's
35where
36 M: Map<V> + 's,
37{
38 sieve.closure(seeds).map(move |p| (p, map.get(p)))
39}
40
41#[cfg(feature = "map-adapter")]
42#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
43pub fn restrict_star<'s, M, V: 's>(
51 sieve: &'s impl Sieve<Point = PointId>,
52 map: &'s M,
53 seeds: impl IntoIterator<Item = PointId>,
54) -> impl Iterator<Item = (PointId, &'s [V])> + 's
55where
56 M: Map<V> + 's,
57{
58 sieve.star(seeds).map(move |p| (p, map.get(p)))
59}
60
61#[cfg(feature = "map-adapter")]
62#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
63pub fn restrict_closure_vec<'s, M, V: 's>(
69 sieve: &'s impl Sieve<Point = PointId>,
70 map: &'s M,
71 seeds: impl IntoIterator<Item = PointId>,
72) -> Vec<(PointId, &'s [V])>
73where
74 M: Map<V> + 's,
75{
76 restrict_closure(sieve, map, seeds).collect()
77}
78
79#[cfg(feature = "map-adapter")]
80#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
81pub fn restrict_star_vec<'s, M, V: 's>(
87 sieve: &'s impl Sieve<Point = PointId>,
88 map: &'s M,
89 seeds: impl IntoIterator<Item = PointId>,
90) -> Vec<(PointId, &'s [V])>
91where
92 M: Map<V> + 's,
93{
94 restrict_star(sieve, map, seeds).collect()
95}
96
97pub fn try_restrict_closure<'s, M, V: 's>(
105 sieve: &'s impl Sieve<Point = PointId>,
106 map: &'s M,
107 seeds: impl IntoIterator<Item = PointId>,
108) -> impl Iterator<Item = Result<(PointId, &'s [V]), MeshSieveError>> + 's
109where
110 M: FallibleMap<V> + 's,
111{
112 sieve
113 .closure(seeds)
114 .map(move |p| map.try_get(p).map(|sl| (p, sl)))
115}
116
117pub fn try_restrict_star<'s, M, V: 's>(
125 sieve: &'s impl Sieve<Point = PointId>,
126 map: &'s M,
127 seeds: impl IntoIterator<Item = PointId>,
128) -> impl Iterator<Item = Result<(PointId, &'s [V]), MeshSieveError>> + 's
129where
130 M: FallibleMap<V> + 's,
131{
132 sieve
133 .star(seeds)
134 .map(move |p| map.try_get(p).map(|sl| (p, sl)))
135}
136
137pub fn try_restrict_closure_vec<'s, M, V: 's>(
142 sieve: &'s impl Sieve<Point = PointId>,
143 map: &'s M,
144 seeds: impl IntoIterator<Item = PointId>,
145) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
146where
147 M: FallibleMap<V> + 's,
148{
149 try_restrict_closure(sieve, map, seeds).collect()
150}
151
152pub fn try_restrict_star_vec<'s, M, V: 's>(
157 sieve: &'s impl Sieve<Point = PointId>,
158 map: &'s M,
159 seeds: impl IntoIterator<Item = PointId>,
160) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
161where
162 M: FallibleMap<V> + 's,
163{
164 try_restrict_star(sieve, map, seeds).collect()
165}
166
167#[cfg(feature = "rayon")]
168pub fn try_restrict_closure_vec_parallel<'s, M, V: Send + Sync + 's>(
169 sieve: &impl Sieve<Point = PointId>,
170 map: &'s M,
171 seeds: impl IntoIterator<Item = PointId>,
172) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
173where
174 M: FallibleMap<V> + Sync + 's,
175{
176 use rayon::prelude::*;
177 let pts: Vec<_> = sieve.closure(seeds).collect();
178 pts.par_iter()
179 .map(|&p| map.try_get(p).map(|sl| (p, sl)))
180 .collect::<Result<Vec<_>, MeshSieveError>>()
181}
182
183#[cfg(feature = "rayon")]
184pub fn try_restrict_star_vec_parallel<'s, M, V: Send + Sync + 's>(
185 sieve: &impl Sieve<Point = PointId>,
186 map: &'s M,
187 seeds: impl IntoIterator<Item = PointId>,
188) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
189where
190 M: FallibleMap<V> + Sync + 's,
191{
192 use rayon::prelude::*;
193 let pts: Vec<_> = sieve.star(seeds).collect();
194 pts.par_iter()
195 .map(|&p| map.try_get(p).map(|sl| (p, sl)))
196 .collect::<Result<Vec<_>, MeshSieveError>>()
197}
198
199pub struct ReadOnlyMap<'a, V, S: Storage<V> = VecStorage<V>> {
201 pub section: &'a crate::data::section::Section<V, S>,
203 _marker: PhantomData<V>,
204}
205
206impl<'a, V, S> FallibleMap<V> for ReadOnlyMap<'a, V, S>
207where
208 S: Storage<V>,
209{
210 #[inline]
211 fn try_get(&self, p: crate::topology::point::PointId) -> Result<&[V], MeshSieveError> {
212 self.section.try_restrict(p)
213 }
214
215 #[inline]
216 fn try_get_mut(
217 &mut self,
218 _p: crate::topology::point::PointId,
219 ) -> Result<&mut [V], MeshSieveError> {
220 Err(MeshSieveError::UnsupportedStackOperation(
221 "ReadOnlyMap::try_get_mut",
222 ))
223 }
224}
225
226#[cfg(feature = "map-adapter")]
227#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
228impl<'a, V, S> Map<V> for ReadOnlyMap<'a, V, S>
229where
230 S: Storage<V>,
231{
232 fn get(&self, p: crate::topology::point::PointId) -> &[V] {
233 self.section
234 .try_restrict(p)
235 .unwrap_or_else(|e| panic!("ReadOnlyMap::get({p:?}) failed: {e}"))
236 }
237 }
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243 use crate::data::atlas::Atlas;
244 #[cfg(feature = "map-adapter")]
245 use crate::data::section::Map;
246 use crate::data::section::{FallibleMap, Section};
247 use crate::data::storage::VecStorage;
248 use crate::topology::point::PointId;
249 use crate::topology::sieve::in_memory::InMemorySieve;
250
251 fn v(i: u64) -> PointId {
252 PointId::new(i).unwrap()
253 }
254
255 #[test]
256 fn restrict_helpers_basic() {
257 let mut s = InMemorySieve::<PointId, ()>::default();
259 s.add_arrow(v(1), v(2), ());
260 s.add_arrow(v(2), v(3), ());
261 let mut atlas = Atlas::default();
262 atlas.try_insert(v(1), 1).unwrap();
263 atlas.try_insert(v(2), 1).unwrap();
264 atlas.try_insert(v(3), 1).unwrap();
265 let mut sec = Section::<i32, VecStorage<i32>>::new(atlas);
266 sec.try_set(v(1), &[10]).unwrap();
267 sec.try_set(v(2), &[20]).unwrap();
268 sec.try_set(v(3), &[30]).unwrap();
269
270 let expected: Vec<_> = s
272 .closure([v(1)])
273 .map(|p| (p, sec.try_restrict(p).unwrap()))
274 .collect();
275 assert_eq!(
276 try_restrict_closure_vec(&s, &sec, [v(1)]).unwrap(),
277 expected
278 );
279
280 assert!(matches!(
282 try_restrict_closure_vec(&s, &sec, [v(99)]),
283 Err(MeshSieveError::PointNotInAtlas(pid)) if pid == v(99)
284 ));
285
286 #[allow(unused_mut)]
288 let mut rom = ReadOnlyMap {
289 section: &sec,
290 _marker: PhantomData,
291 };
292 assert_eq!(
293 <ReadOnlyMap<'_, i32, VecStorage<i32>> as FallibleMap<i32>>::try_get(&rom, v(3))
294 .unwrap(),
295 sec.try_restrict(v(3)).unwrap()
296 );
297 assert!(
298 <ReadOnlyMap<'_, i32, VecStorage<i32>> as FallibleMap<i32>>::try_get(&rom, v(99))
299 .is_err()
300 );
301
302 #[cfg(feature = "map-adapter")]
303 assert!(
304 <ReadOnlyMap<'_, i32, VecStorage<i32>> as Map<i32>>::get_mut(&mut rom, v(3)).is_none()
305 );
306 }
307
308 #[cfg(feature = "map-adapter")]
309 #[test]
310 fn restrict_helpers_legacy() {
311 let mut s = InMemorySieve::<PointId, ()>::default();
313 s.add_arrow(v(1), v(2), ());
314 s.add_arrow(v(2), v(3), ());
315 let mut atlas = Atlas::default();
316 atlas.try_insert(v(1), 1).unwrap();
317 atlas.try_insert(v(2), 1).unwrap();
318 atlas.try_insert(v(3), 1).unwrap();
319 let mut sec = Section::<i32, VecStorage<i32>>::new(atlas);
320 sec.try_set(v(1), &[10]).unwrap();
321 sec.try_set(v(2), &[20]).unwrap();
322 sec.try_set(v(3), &[30]).unwrap();
323
324 let out: Vec<_> = restrict_closure(&s, &sec, [v(1)]).collect();
326 let expected: Vec<_> = s
327 .closure([v(1)])
328 .map(|p| (p, sec.try_restrict(p).unwrap()))
329 .collect();
330 assert_eq!(out, expected);
331 let empty: Vec<_> = restrict_star(&s, &sec, std::iter::empty()).collect();
333 assert!(empty.is_empty());
334 assert_eq!(
336 restrict_closure_vec(&s, &sec, [v(2)]),
337 restrict_closure(&s, &sec, [v(2)]).collect::<Vec<_>>()
338 );
339 assert_eq!(
341 try_restrict_closure_vec(&s, &sec, [v(1)]).unwrap(),
342 restrict_closure_vec(&s, &sec, [v(1)])
343 );
344 assert!(std::panic::catch_unwind(|| restrict_closure_vec(&s, &sec, [v(99)])).is_err());
346 }
347}