gistools/readers/gpx/
mod.rs1pub mod spec;
3
4use crate::parsers::FeatureReader;
5use alloc::{string::String, vec::Vec};
6use s2json::{MValueCompatible, VectorFeature};
7pub use spec::*;
8
9#[derive(Debug, Default, Clone, PartialEq, MValueCompatible)]
11pub struct GPXProperties {
12 pub name: Option<String>,
14 pub cmt: Option<String>,
16 pub desc: Option<String>,
18 pub src: Option<String>,
20 pub link: Option<Vec<GPXLink>>,
22 pub number: Option<usize>,
24 pub route_type: Option<String>,
26 pub track_type: Option<String>,
28}
29
30pub type GPXVectorFeature = VectorFeature<(), GPXProperties, GPXWaypoint>;
32
33#[derive(Debug, Clone)]
71pub struct GPXReader {
72 pub gpx: GPX,
74}
75impl GPXReader {
76 pub fn new(input: &str) -> Self {
78 Self { gpx: GPX::new(input) }
79 }
80 pub fn metadata(&self) -> GPXMetadata {
82 self.gpx.metadata.clone().unwrap_or_default()
83 }
84}
85#[derive(Debug)]
87pub struct GPXIterator<'a> {
88 reader: &'a GPXReader,
89 wpt_offset: usize,
90 wpt_count: usize,
91 rte_offset: usize,
92 rte_count: usize,
93 trk_offset: usize,
94 trk_count: usize,
95}
96impl Iterator for GPXIterator<'_> {
97 type Item = GPXVectorFeature;
98
99 fn next(&mut self) -> Option<Self::Item> {
100 let gpx = &self.reader.gpx;
101 if self.wpt_offset < self.wpt_count {
102 self.wpt_offset += 1;
103 return gpx.wpt.as_ref().map(|w| w[self.wpt_offset - 1].feature());
104 }
105 if self.rte_offset < self.rte_count {
106 self.rte_offset += 1;
107 return gpx.rte.as_ref().map(|w| w[self.rte_offset - 1].feature());
108 }
109 if self.trk_offset < self.trk_count {
110 self.trk_offset += 1;
111 return gpx.trk.as_ref().map(|w| w[self.trk_offset - 1].feature());
112 }
113 None
114 }
115}
116impl FeatureReader<(), GPXProperties, GPXWaypoint> for GPXReader {
118 type FeatureIterator<'a> = GPXIterator<'a>;
119
120 fn iter(&self) -> Self::FeatureIterator<'_> {
121 GPXIterator {
122 reader: self,
123 wpt_offset: 0,
124 wpt_count: self.gpx.wpt.as_ref().map(|w| w.len()).unwrap_or_default(),
125 rte_offset: 0,
126 rte_count: self.gpx.rte.as_ref().map(|r| r.len()).unwrap_or_default(),
127 trk_offset: 0,
128 trk_count: self.gpx.trk.as_ref().map(|t| t.len()).unwrap_or_default(),
129 }
130 }
131
132 fn par_iter(&self, pool_size: usize, thread_id: usize) -> Self::FeatureIterator<'_> {
134 let mut wpt_count = self.gpx.wpt.as_ref().map(|w| w.len()).unwrap_or_default();
135 let mut rte_count = self.gpx.rte.as_ref().map(|r| r.len()).unwrap_or_default();
136 let mut trk_count = self.gpx.trk.as_ref().map(|t| t.len()).unwrap_or_default();
137 let wpt_offset = wpt_count * thread_id / pool_size;
138 wpt_count = wpt_count * (thread_id + 1) / pool_size;
139 let rte_offset = rte_count * thread_id / pool_size;
140 rte_count = rte_count * (thread_id + 1) / pool_size;
141 let trk_offset = trk_count * thread_id / pool_size;
142 trk_count = trk_count * (thread_id + 1) / pool_size;
143 GPXIterator {
144 reader: self,
145 wpt_offset,
146 wpt_count,
147 rte_offset,
148 rte_count,
149 trk_offset,
150 trk_count,
151 }
152 }
153}