kml_to_fgfp/route/
handlers.rs1use std::{error::Error, io::Write};
2
3use xml::writer::EventWriter;
4
5use super::Airport;
6
7pub struct Waypoint {
9 pub number: usize,
10 pub ident: String,
11 pub lon: f64,
12 pub lat: f64,
13 pub altitude: usize,
14}
15
16pub enum LookingFor {
26 OpeningPlacemark,
27 OpeningName,
28 ContentName,
29 ClosingName,
30 OpeningStyleUrl,
31 ContentStyleUrl,
32 ClosingStyleUrl,
33 OpeningCoordinates,
34 ContentCoordinates,
35 ClosingCoordinates,
36 ClosingPlacemark,
37}
38
39pub fn handle_start_event(
41 mut waypoint: Waypoint,
42 mut current_search: LookingFor,
43 mut drop: bool,
44 wp: usize,
45 name: &str,
46) -> (Waypoint, LookingFor, bool) {
47 if matches!(current_search, LookingFor::OpeningPlacemark) && name == "Placemark" {
49 waypoint.number = wp;
50 current_search = LookingFor::OpeningName;
51 drop = false;
52 }
53
54 if matches!(current_search, LookingFor::OpeningName) && name == "name" {
56 current_search = LookingFor::ContentName;
57 }
58
59 if matches!(current_search, LookingFor::OpeningStyleUrl) && name == "styleUrl" {
61 current_search = LookingFor::ContentStyleUrl;
62 }
63
64 if matches!(current_search, LookingFor::OpeningCoordinates) && name == "coordinates" {
66 current_search = LookingFor::ContentCoordinates;
67 }
68
69 (waypoint, current_search, drop)
70}
71
72pub fn handle_characters_event(
74 mut waypoint: Waypoint,
75 mut current_search: LookingFor,
76 mut drop: bool,
77 line: String,
78 departure_airport: &Option<Airport>,
79 destination_airport: &Option<Airport>,
80) -> (Waypoint, LookingFor, bool) {
81 if matches!(current_search, LookingFor::ContentName) {
83 waypoint.ident = String::from(&line);
84 current_search = LookingFor::ClosingName;
85
86 if let Some(airport) = departure_airport {
88 if line == airport.ident {
89 current_search = LookingFor::ClosingPlacemark;
90 drop = true;
91 }
92 }
93
94 if let Some(airport) = destination_airport {
95 if line == airport.ident {
96 current_search = LookingFor::ClosingPlacemark;
97 drop = true;
98 }
99 }
100 }
101
102 if matches!(current_search, LookingFor::ContentStyleUrl) {
104 if line != "#FixMark" {
105 drop = true;
106
107 current_search = LookingFor::ClosingPlacemark;
110
111 return (waypoint, current_search, drop);
112 }
113 current_search = LookingFor::ClosingStyleUrl;
114 }
115
116 if matches!(current_search, LookingFor::ContentCoordinates) {
118 let data: Vec<&str> = line.split(',').map(|l| l.trim()).collect();
119
120 let mut message = String::new();
121
122 waypoint.lon = match data[0].parse() {
123 Ok(d) => d,
124 Err(e) => {
125 message = e.to_string();
126 0f64
127 }
128 };
129 waypoint.lat = match data[1].parse() {
130 Ok(d) => d,
131 Err(e) => {
132 message = e.to_string();
133 0f64
134 }
135 };
136 waypoint.altitude = {
137 let meters: f64 = match data[2].parse() {
138 Ok(d) => d,
139 Err(e) => {
140 message = e.to_string();
141 0f64
142 }
143 };
144
145 let feet = (meters * 3.280839895 / 100.0).round() * 100.0;
149 feet as usize
150 };
151
152 if !message.is_empty() {
153 eprintln!(
154 "\x1B[01;33mDropping\x1B[00;01m {}\x1B[00m waypoint: {}",
155 waypoint.ident, message
156 );
157 drop = true;
158 }
159
160 current_search = LookingFor::ClosingCoordinates;
161 }
162
163 (waypoint, current_search, drop)
164}
165
166pub fn handle_end_event<W: Write>(
168 writer: &mut EventWriter<W>,
169 waypoint: Waypoint,
170 mut current_search: LookingFor,
171 drop: bool,
172 mut wp: usize,
173 name: &str,
174) -> Result<(Waypoint, LookingFor, usize), Box<dyn Error>> {
175 if matches!(current_search, LookingFor::ClosingName) && name == "name" {
177 current_search = LookingFor::OpeningStyleUrl;
178 }
179
180 if matches!(current_search, LookingFor::ClosingStyleUrl) && name == "styleUrl" {
182 current_search = LookingFor::OpeningCoordinates;
183 }
184
185 if matches!(current_search, LookingFor::ClosingCoordinates) && name == "coordinates" {
187 current_search = LookingFor::ClosingPlacemark;
188 }
189
190 if matches!(current_search, LookingFor::ClosingPlacemark) && name == "Placemark" {
192 if !drop {
193 super::write_waypoint(writer, &waypoint)?;
194 wp += 1;
195 }
196 current_search = LookingFor::OpeningPlacemark;
197 }
198
199 Ok((waypoint, current_search, wp))
200}