sct_reader/loaders/ese/
reader.rs1use std::str::FromStr;
2use std::io::BufRead;
3use crate::loaders::euroscope::error::Error;
4use crate::loaders::euroscope::SectorResult;
5
6use super::partial::PartialEse;
7use super::Ese;
8
9
10#[derive(Debug)]
11enum FileSection {
12 FreeText,
13 SidsStars,
14 Positions,
15 Airspace,
16 Radar,
17 Ground,
18}
19
20impl FromStr for FileSection {
21 type Err = Error;
22 fn from_str(s: &str) -> Result<Self, Self::Err> {
23 let new_section = match s.to_uppercase().as_str() {
24 "[FREETEXT]" => Self::FreeText,
25 "[SIDSSTARS]" => Self::SidsStars,
26 "[POSITIONS]" => Self::Positions,
27 "[AIRSPACE]" => Self::Airspace,
28 "[RADAR]" => Self::Radar,
29 "[GROUND]" => Self::Ground,
30 _ => return Err(Error::InvalidFileSection),
31 };
32 Ok(new_section)
33 }
34}
35
36pub struct EseReader<R: BufRead> {
37 source: R,
38 current_section: FileSection,
39 partial_ese: PartialEse,
40 errors: Vec<(usize, String, Error)>,
41}
42
43impl<R: BufRead> EseReader<R> {
44 pub fn new(source: R) -> Self {
45 Self {
46 source,
47 current_section: FileSection::FreeText,
48 partial_ese: PartialEse::default(),
49 errors: vec![],
50 }
51 }
52
53 pub fn try_read(mut self) -> SectorResult<Ese> {
54 for (mut line_number, line) in self.source.lines().enumerate() {
55 if let Ok(line) = line {
56 let mut line = line.trim_end();
57 line_number += 1;
58
59 if line.is_empty() || line.starts_with(';') {
60 continue;
61 }
62 if line.contains(';') {
63 let mut line_split = line.split(';');
64 line = line_split.next().unwrap().trim_end();
65 }
66 if line.starts_with('[') {
67 match FileSection::from_str(line) {
68 Ok(new_section) => self.current_section = new_section,
69 Err(e) => self.errors.push((line_number + 1, line.to_owned(), e)),
70 }
71 continue;
72 }
73 if line.starts_with("OFFSET") {
74 if let Err(e) = self.partial_ese.parse_offset(line) {
75 self.errors.push((line_number, line.to_owned(), e));
76 }
77 continue;
78 }
79 if line.starts_with("#define") {
80 if let Err(e) = self.partial_ese.parse_colour_line(line) {
81 self.errors.push((line_number, line.to_owned(), e));
82 }
83 continue;
84 }
85
86 let result = match self.current_section {
87 FileSection::FreeText => self.partial_ese.parse_freetext_line(line),
88 FileSection::SidsStars => self.partial_ese.parse_sids_stars_line(line),
89 FileSection::Positions => self.partial_ese.parse_atc_position_line(line),
90 _ => continue,
94 };
95 if let Err(e) = result {
96 self.errors.push((line_number, line.to_owned(), e));
97 }
98 }
99 }
100
101 let mut ese: Ese = self.partial_ese.try_into()?;
102 ese.non_critical_errors = self.errors;
103 Ok(ese)
104 }
105}