geo_traits/
geometry_collection.rs

1use std::marker::PhantomData;
2
3use crate::iterator::GeometryCollectionIterator;
4use crate::{GeometryTrait, UnimplementedGeometry};
5#[cfg(feature = "geo-types")]
6use geo_types::{CoordNum, Geometry, GeometryCollection};
7
8/// A trait for accessing data from a generic GeometryCollection.
9///
10/// A GeometryCollection is a collection of [Geometry][GeometryTrait] types.
11pub trait GeometryCollectionTrait: Sized + GeometryTrait {
12    /// The type of each underlying geometry, which implements [GeometryTrait]
13    type GeometryType<'a>: 'a + GeometryTrait<T = Self::T>
14    where
15        Self: 'a;
16
17    /// An iterator over the geometries in this GeometryCollection
18    fn geometries(
19        &self,
20    ) -> impl DoubleEndedIterator + ExactSizeIterator<Item = Self::GeometryType<'_>> {
21        GeometryCollectionIterator::new(self, 0, self.num_geometries())
22    }
23
24    /// The number of geometries in this GeometryCollection
25    fn num_geometries(&self) -> usize;
26
27    /// Access to a specified geometry in this GeometryCollection
28    /// Will return None if the provided index is out of bounds
29    fn geometry(&self, i: usize) -> Option<Self::GeometryType<'_>> {
30        if i >= self.num_geometries() {
31            None
32        } else {
33            unsafe { Some(self.geometry_unchecked(i)) }
34        }
35    }
36
37    /// Access to a specified geometry in this GeometryCollection
38    ///
39    /// # Safety
40    ///
41    /// Accessing an index out of bounds is UB.
42    unsafe fn geometry_unchecked(&self, i: usize) -> Self::GeometryType<'_>;
43}
44
45#[cfg(feature = "geo-types")]
46impl<T: CoordNum> GeometryCollectionTrait for GeometryCollection<T> {
47    type GeometryType<'a>
48        = &'a Geometry<Self::T>
49    where
50        Self: 'a;
51
52    fn num_geometries(&self) -> usize {
53        self.0.len()
54    }
55
56    unsafe fn geometry_unchecked(&self, i: usize) -> Self::GeometryType<'_> {
57        self.0.get_unchecked(i)
58    }
59}
60
61#[cfg(feature = "geo-types")]
62impl<'a, T: CoordNum> GeometryCollectionTrait for &'a GeometryCollection<T> {
63    type GeometryType<'b>
64        = &'a Geometry<Self::T>
65    where
66        Self: 'b;
67
68    fn num_geometries(&self) -> usize {
69        self.0.len()
70    }
71
72    unsafe fn geometry_unchecked(&self, i: usize) -> Self::GeometryType<'_> {
73        self.0.get_unchecked(i)
74    }
75}
76
77/// An empty struct that implements [GeometryCollectionTrait].
78///
79/// This can be used as the `GeometryCollectionType` of the `GeometryTrait` by implementations that
80/// don't have a GeometryCollection concept
81pub struct UnimplementedGeometryCollection<T>(PhantomData<T>);
82
83impl<T> GeometryCollectionTrait for UnimplementedGeometryCollection<T> {
84    type GeometryType<'a>
85        = UnimplementedGeometry<Self::T>
86    where
87        Self: 'a;
88
89    fn num_geometries(&self) -> usize {
90        unimplemented!()
91    }
92
93    unsafe fn geometry_unchecked(&self, _i: usize) -> Self::GeometryType<'_> {
94        unimplemented!()
95    }
96}