use crate::data::section::FallibleMap;
#[cfg(feature = "map-adapter")]
use crate::data::section::Map;
use crate::data::storage::{Storage, VecStorage};
use crate::mesh_error::MeshSieveError;
use crate::topology::point::PointId;
use crate::topology::sieve::Sieve;
use core::marker::PhantomData;
#[cfg(feature = "map-adapter")]
#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
pub fn restrict_closure<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> impl Iterator<Item = (PointId, &'s [V])> + 's
where
M: Map<V> + 's,
{
sieve.closure(seeds).map(move |p| (p, map.get(p)))
}
#[cfg(feature = "map-adapter")]
#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
pub fn restrict_star<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> impl Iterator<Item = (PointId, &'s [V])> + 's
where
M: Map<V> + 's,
{
sieve.star(seeds).map(move |p| (p, map.get(p)))
}
#[cfg(feature = "map-adapter")]
#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
pub fn restrict_closure_vec<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> Vec<(PointId, &'s [V])>
where
M: Map<V> + 's,
{
restrict_closure(sieve, map, seeds).collect()
}
#[cfg(feature = "map-adapter")]
#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
pub fn restrict_star_vec<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> Vec<(PointId, &'s [V])>
where
M: Map<V> + 's,
{
restrict_star(sieve, map, seeds).collect()
}
pub fn try_restrict_closure<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> impl Iterator<Item = Result<(PointId, &'s [V]), MeshSieveError>> + 's
where
M: FallibleMap<V> + 's,
{
sieve
.closure(seeds)
.map(move |p| map.try_get(p).map(|sl| (p, sl)))
}
pub fn try_restrict_star<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> impl Iterator<Item = Result<(PointId, &'s [V]), MeshSieveError>> + 's
where
M: FallibleMap<V> + 's,
{
sieve
.star(seeds)
.map(move |p| map.try_get(p).map(|sl| (p, sl)))
}
pub fn try_restrict_closure_vec<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
where
M: FallibleMap<V> + 's,
{
try_restrict_closure(sieve, map, seeds).collect()
}
pub fn try_restrict_star_vec<'s, M, V: 's>(
sieve: &'s impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
where
M: FallibleMap<V> + 's,
{
try_restrict_star(sieve, map, seeds).collect()
}
#[cfg(feature = "rayon")]
pub fn try_restrict_closure_vec_parallel<'s, M, V: Send + Sync + 's>(
sieve: &impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
where
M: FallibleMap<V> + Sync + 's,
{
use rayon::prelude::*;
let pts: Vec<_> = sieve.closure(seeds).collect();
pts.par_iter()
.map(|&p| map.try_get(p).map(|sl| (p, sl)))
.collect::<Result<Vec<_>, MeshSieveError>>()
}
#[cfg(feature = "rayon")]
pub fn try_restrict_star_vec_parallel<'s, M, V: Send + Sync + 's>(
sieve: &impl Sieve<Point = PointId>,
map: &'s M,
seeds: impl IntoIterator<Item = PointId>,
) -> Result<Vec<(PointId, &'s [V])>, MeshSieveError>
where
M: FallibleMap<V> + Sync + 's,
{
use rayon::prelude::*;
let pts: Vec<_> = sieve.star(seeds).collect();
pts.par_iter()
.map(|&p| map.try_get(p).map(|sl| (p, sl)))
.collect::<Result<Vec<_>, MeshSieveError>>()
}
pub struct ReadOnlyMap<'a, V, S: Storage<V> = VecStorage<V>> {
pub section: &'a crate::data::section::Section<V, S>,
_marker: PhantomData<V>,
}
impl<'a, V, S> FallibleMap<V> for ReadOnlyMap<'a, V, S>
where
S: Storage<V>,
{
#[inline]
fn try_get(&self, p: crate::topology::point::PointId) -> Result<&[V], MeshSieveError> {
self.section.try_restrict(p)
}
#[inline]
fn try_get_mut(
&mut self,
_p: crate::topology::point::PointId,
) -> Result<&mut [V], MeshSieveError> {
Err(MeshSieveError::UnsupportedStackOperation(
"ReadOnlyMap::try_get_mut",
))
}
}
#[cfg(feature = "map-adapter")]
#[cfg_attr(docsrs, doc(cfg(feature = "map-adapter")))]
impl<'a, V, S> Map<V> for ReadOnlyMap<'a, V, S>
where
S: Storage<V>,
{
fn get(&self, p: crate::topology::point::PointId) -> &[V] {
self.section
.try_restrict(p)
.unwrap_or_else(|e| panic!("ReadOnlyMap::get({p:?}) failed: {e}"))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::data::atlas::Atlas;
#[cfg(feature = "map-adapter")]
use crate::data::section::Map;
use crate::data::section::{FallibleMap, Section};
use crate::data::storage::VecStorage;
use crate::topology::point::PointId;
use crate::topology::sieve::in_memory::InMemorySieve;
fn v(i: u64) -> PointId {
PointId::new(i).unwrap()
}
#[test]
fn restrict_helpers_basic() {
let mut s = InMemorySieve::<PointId, ()>::default();
s.add_arrow(v(1), v(2), ());
s.add_arrow(v(2), v(3), ());
let mut atlas = Atlas::default();
atlas.try_insert(v(1), 1).unwrap();
atlas.try_insert(v(2), 1).unwrap();
atlas.try_insert(v(3), 1).unwrap();
let mut sec = Section::<i32, VecStorage<i32>>::new(atlas);
sec.try_set(v(1), &[10]).unwrap();
sec.try_set(v(2), &[20]).unwrap();
sec.try_set(v(3), &[30]).unwrap();
let expected: Vec<_> = s
.closure([v(1)])
.map(|p| (p, sec.try_restrict(p).unwrap()))
.collect();
assert_eq!(
try_restrict_closure_vec(&s, &sec, [v(1)]).unwrap(),
expected
);
assert!(matches!(
try_restrict_closure_vec(&s, &sec, [v(99)]),
Err(MeshSieveError::PointNotInAtlas(pid)) if pid == v(99)
));
#[allow(unused_mut)]
let mut rom = ReadOnlyMap {
section: &sec,
_marker: PhantomData,
};
assert_eq!(
<ReadOnlyMap<'_, i32, VecStorage<i32>> as FallibleMap<i32>>::try_get(&rom, v(3))
.unwrap(),
sec.try_restrict(v(3)).unwrap()
);
assert!(
<ReadOnlyMap<'_, i32, VecStorage<i32>> as FallibleMap<i32>>::try_get(&rom, v(99))
.is_err()
);
#[cfg(feature = "map-adapter")]
assert!(
<ReadOnlyMap<'_, i32, VecStorage<i32>> as Map<i32>>::get_mut(&mut rom, v(3)).is_none()
);
}
#[cfg(feature = "map-adapter")]
#[test]
fn restrict_helpers_legacy() {
let mut s = InMemorySieve::<PointId, ()>::default();
s.add_arrow(v(1), v(2), ());
s.add_arrow(v(2), v(3), ());
let mut atlas = Atlas::default();
atlas.try_insert(v(1), 1).unwrap();
atlas.try_insert(v(2), 1).unwrap();
atlas.try_insert(v(3), 1).unwrap();
let mut sec = Section::<i32, VecStorage<i32>>::new(atlas);
sec.try_set(v(1), &[10]).unwrap();
sec.try_set(v(2), &[20]).unwrap();
sec.try_set(v(3), &[30]).unwrap();
let out: Vec<_> = restrict_closure(&s, &sec, [v(1)]).collect();
let expected: Vec<_> = s
.closure([v(1)])
.map(|p| (p, sec.try_restrict(p).unwrap()))
.collect();
assert_eq!(out, expected);
let empty: Vec<_> = restrict_star(&s, &sec, std::iter::empty()).collect();
assert!(empty.is_empty());
assert_eq!(
restrict_closure_vec(&s, &sec, [v(2)]),
restrict_closure(&s, &sec, [v(2)]).collect::<Vec<_>>()
);
assert_eq!(
try_restrict_closure_vec(&s, &sec, [v(1)]).unwrap(),
restrict_closure_vec(&s, &sec, [v(1)])
);
assert!(std::panic::catch_unwind(|| restrict_closure_vec(&s, &sec, [v(99)])).is_err());
}
}