gistools/readers/gbfs/schema_v1/
mod.rs1mod free_bike_status;
2mod gbfs;
3mod gbfs_versions;
4mod station_information;
5mod station_status;
6mod system_alerts;
7mod system_calendar;
8mod system_hours;
9mod system_information;
10mod system_pricing_plans;
11mod system_regions;
12
13use crate::{parsers::FeatureReader, util::fetch_url};
14use alloc::{format, string::String, vec, vec::Vec};
15pub use free_bike_status::*;
16pub use gbfs::*;
17pub use gbfs_versions::*;
18use s2json::{MValue, Properties, VectorFeature, VectorGeometry, VectorPoint};
19use serde::{Deserialize, Serialize};
20pub use station_information::*;
21pub use station_status::*;
22pub use system_alerts::*;
23pub use system_calendar::*;
24pub use system_hours::*;
25pub use system_information::*;
26pub use system_pricing_plans::*;
27pub use system_regions::*;
28
29#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, MValue)]
31pub struct GBFSStationV1FeaturesProperties {
32 pub station_id: String,
34 pub name: String,
36 pub short_name: Option<String>,
38 pub address: Option<String>,
40 pub cross_street: Option<String>,
42 pub region_id: Option<String>,
44 pub post_code: Option<String>,
46 pub capacity: Option<u64>,
48}
49impl From<&GBFSStationInformationV11Station> for GBFSStationV1FeaturesProperties {
50 fn from(station: &GBFSStationInformationV11Station) -> Self {
51 GBFSStationV1FeaturesProperties {
52 station_id: station.station_id.clone(),
53 name: station.name.clone(),
54 short_name: station.short_name.clone(),
55 address: station.address.clone(),
56 cross_street: station.cross_street.clone(),
57 region_id: station.region_id.clone(),
58 post_code: station.post_code.clone(),
59 capacity: station.capacity,
60 }
61 }
62}
63
64pub type GBFSStationFeatureV1 = VectorFeature<(), GBFSStationV1FeaturesProperties, MValue>;
66
67pub type GBFSBikeFeatureV1 = VectorFeature<(), GBFSFreeBikeV11, MValue>;
69
70#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
72pub struct GBFSReaderV1 {
73 pub free_bike_status: Option<GBFSFreeBikeStatusV1>,
75 pub gbfs: GBFSV1,
77 pub gbfs_versions: Option<GBFSVersionsV1>,
79 pub station_information: Option<GBFSStationInformationV1>,
81 pub station_status: Option<GBFSStationStatusV1>,
83 pub system_alerts: Option<GBFSSystemAlertsV1>,
85 pub system_calendar: Option<GBFSSystemCalendarV1>,
87 pub system_hours: Option<GBFSSystemHoursV1>,
89 pub system_information: GBFSSystemInformationV1,
91 pub system_pricing_plans: Option<GBFSSystemPricingPlansV1>,
93 pub system_regions: Option<GBFSSystemRegionsV1>,
95}
96impl GBFSReaderV1 {
97 pub fn features(&self) -> Vec<VectorFeature> {
99 let mut res = vec![];
100
101 res.extend(self.station_features().iter().map(|f| f.to_m_vector_feature(|_| None)));
102 res.extend(self.bike_features().iter().map(|f| f.to_m_vector_feature(|_| None)));
103
104 res
105 }
106
107 pub fn station_features(&self) -> Vec<GBFSStationFeatureV1> {
109 let mut res = vec![];
110
111 if let Some(station_information) = &self.station_information {
112 for station in &station_information.data.stations {
113 res.push(VectorFeature::new_wm(
114 None,
115 GBFSStationV1FeaturesProperties::from(station),
116 VectorGeometry::new_point(VectorPoint::from_xy(station.lon, station.lat), None),
117 None,
118 ));
119 }
120 }
121
122 res
123 }
124
125 pub fn bike_features(&self) -> Vec<GBFSBikeFeatureV1> {
127 let mut res = vec![];
128
129 if let Some(free_bike_status) = &self.free_bike_status {
130 for bike in &free_bike_status.data.bikes {
131 res.push(VectorFeature::new_wm(
132 None,
133 bike.clone(),
134 VectorGeometry::new_point(VectorPoint::from_xy(bike.lon, bike.lat), None),
135 None,
136 ));
137 }
138 }
139
140 res
141 }
142}
143
144#[derive(Debug)]
146pub struct GBFSIteratorV1 {
147 features: Vec<VectorFeature>,
148 index: usize,
149 len: usize,
150}
151impl Iterator for GBFSIteratorV1 {
152 type Item = VectorFeature;
153
154 fn next(&mut self) -> Option<Self::Item> {
155 if self.index >= self.len {
156 return None;
157 }
158 self.index += 1;
159 self.features.get(self.index - 1).cloned()
160 }
161}
162impl FeatureReader<(), Properties, MValue> for GBFSReaderV1 {
164 type FeatureIterator<'a> = GBFSIteratorV1;
165
166 fn iter(&self) -> Self::FeatureIterator<'_> {
167 let features: Vec<VectorFeature> =
168 self.features().iter().map(|f| f.to_m_vector_feature(|_| None)).collect();
169 let len = features.len();
170 GBFSIteratorV1 { features, index: 0, len }
171 }
172
173 fn par_iter(&self, pool_size: usize, thread_id: usize) -> Self::FeatureIterator<'_> {
174 let features: Vec<VectorFeature> =
175 self.features().iter().map(|f| f.to_m_vector_feature(|_| None)).collect();
176 let start = features.len() * thread_id / pool_size;
177 let end = features.len() * (thread_id + 1) / pool_size;
178 GBFSIteratorV1 { features, index: start, len: end }
179 }
180}
181
182pub async fn build_gbfs_reader_v1(
192 gbfs: &GBFSV1,
193 locale: Option<String>,
194 path: Option<String>,
195) -> GBFSReaderV1 {
196 let locale = locale.unwrap_or("en".into());
197 let data = &gbfs.data;
198 let first_locale = data.keys().next().unwrap();
199 let feeds = data.get(&locale).unwrap_or(data.get(first_locale).unwrap());
200 let feeds = feeds.feeds.clone();
201
202 let mut reader = GBFSReaderV1 { gbfs: gbfs.clone(), ..Default::default() };
203
204 for feed in feeds {
205 let name = serde_json::to_string(&feed.name).unwrap();
206 if &name == "gbfs" {
207 continue;
208 }
209 let url = if let Some(ref path) = path {
210 format!("{}/{}.json", path, name.trim_matches('"'))
211 } else {
212 feed.url
213 };
214
215 if let Ok(url_data) = fetch_url::<()>(&url, &[], None, None).await {
216 match feed.name {
217 GBFSV11FeedsName::FreeBikeStatus => {
218 reader.free_bike_status = Some(serde_json::from_slice(&url_data).unwrap());
219 }
220 GBFSV11FeedsName::Gbfs => {}
221 GBFSV11FeedsName::GbfsVersions => {
222 reader.gbfs_versions = Some(serde_json::from_slice(&url_data).unwrap());
223 }
224 GBFSV11FeedsName::StationInformation => {
225 reader.station_information = Some(serde_json::from_slice(&url_data).unwrap());
226 }
227 GBFSV11FeedsName::StationStatus => {
228 reader.station_status = Some(serde_json::from_slice(&url_data).unwrap());
229 }
230 GBFSV11FeedsName::SystemAlerts => {
231 reader.system_alerts = Some(serde_json::from_slice(&url_data).unwrap());
232 }
233 GBFSV11FeedsName::SystemCalendar => {
234 reader.system_calendar = Some(serde_json::from_slice(&url_data).unwrap());
235 }
236 GBFSV11FeedsName::SystemHours => {
237 reader.system_hours = Some(serde_json::from_slice(&url_data).unwrap());
238 }
239 GBFSV11FeedsName::SystemInformation => {
240 reader.system_information = serde_json::from_slice(&url_data).unwrap();
241 }
242 GBFSV11FeedsName::SystemPricingPlans => {
243 reader.system_pricing_plans = Some(serde_json::from_slice(&url_data).unwrap());
244 }
245 GBFSV11FeedsName::SystemRegions => {
246 reader.system_regions = Some(serde_json::from_slice(&url_data).unwrap());
247 }
248 }
249 }
250 }
251
252 reader
253}