use core::ops::Range;
use crate::TileError;
use crate::vertex::PolyVertex;
pub(crate) fn offset(len: usize) -> Result<u32, TileError> {
u32::try_from(len).map_err(|_| TileError::GeometryTooLarge)
}
pub(crate) fn span(ends: &[u32], i: usize) -> Range<usize> {
let start = if i == 0 { 0 } else { ends[i - 1] as usize };
start..ends[i] as usize
}
pub struct PolygonView<'a, V: PolyVertex, A = ()> {
verts: &'a [V],
ring_ends: &'a [u32],
first: usize,
end: usize,
attr: &'a A,
}
impl<'a, V: PolyVertex, A> PolygonView<'a, V, A> {
pub(crate) fn new(
verts: &'a [V],
ring_ends: &'a [u32],
rings: Range<usize>,
attr: &'a A,
) -> Self {
Self {
verts,
ring_ends,
first: rings.start,
end: rings.end,
attr,
}
}
#[must_use]
pub fn attr(&self) -> &'a A {
self.attr
}
pub fn iter_rings(&self) -> impl Iterator<Item = RingView<'a, V>> + use<'a, V, A> {
let (verts, ends, first) = (self.verts, self.ring_ends, self.first);
(first..self.end).map(move |r| RingView {
verts: &verts[span(ends, r)],
is_hole: r != first,
})
}
}
pub struct RingView<'a, V: PolyVertex> {
verts: &'a [V],
is_hole: bool,
}
impl<'a, V: PolyVertex> RingView<'a, V> {
#[must_use]
pub fn vertices(&self) -> &'a [V] {
self.verts
}
#[must_use]
pub fn is_hole(&self) -> bool {
self.is_hole
}
}
macro_rules! copy_view {
($($view:ident<$($param:ident),*>: $bound:path),* $(,)?) => {$(
#[allow(
clippy::expl_impl_clone_on_copy,
reason = "a derive would require the vertex and attribute types to be Copy too; some views trip the lint and some do not"
)]
impl<V: $bound, $($param),*> Clone for $view<'_, V, $($param),*> {
fn clone(&self) -> Self {
*self
}
}
impl<V: $bound, $($param),*> Copy for $view<'_, V, $($param),*> {}
)*};
}
pub(crate) use copy_view;
copy_view!(PolygonView<A>: PolyVertex, RingView<>: PolyVertex);