geo_traits/
multi_line_string.rs

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