eterm_parser/
ml.rs

1#[derive(Default, Debug)]
2pub struct Ml<'a> {
3    pub raw_text: &'a str,
4    pub segs: Option<Vec<MlSeg<'a>>>,
5    pub flight_no: Option<&'a str>,
6    pub flight_date: Option<&'a str>,
7    pub criteria: Option<&'a str>,
8}
9
10impl<'a> Ml<'a> {
11    pub fn parse(text: &'a str) -> anyhow::Result<Self> {
12        if text.is_empty() {
13            return Err(anyhow::Error::msg(
14                "ml parameter shouldn't be empty.".to_owned(),
15            ));
16        }
17        let mut mlinfo = Self {
18            raw_text: text,
19            ..Default::default()
20        };
21        let mut lines = text.lines();
22        if let Some(first_line) = lines.next() {
23            if first_line.trim() == "NO-OP" {
24                return Ok(mlinfo);
25            } else if first_line.trim() != "MULTI" {
26                return Err(anyhow::Error::msg("ml must start with 'MULTI'.".to_owned()));
27            }
28        } else {
29            return Ok(mlinfo);
30        }
31
32        if let Some(second_line) = lines.next() {
33            let mut info = second_line.split(&[' ']).filter(|x|!x.is_empty());
34            mlinfo.flight_no = info.next().and_then(|x| Some(x));
35            mlinfo.flight_date = info.next().and_then(|x| Some(x));
36            mlinfo.criteria = info.next().and_then(|x| Some(x));
37        } else {
38            return Ok(mlinfo);
39        }
40        for line in lines {
41            let line = line.trim_end_matches(&['+', '-']);
42
43            if line.trim().len() == 6 {
44                let segment = MlSeg {
45                    org: &line[0..3],
46                    dst: &line[3..],
47                    ..Default::default()
48                };
49                mlinfo.segs.get_or_insert(Vec::new()).push(segment);
50            } else if regex::Regex::is_match(&regex::Regex::new(r"^\s*\d+")?, line) {
51                if let Some(ref mut segs) = &mut mlinfo.segs.as_mut() {
52                    if let Some(seg) = segs.last_mut() {
53                        let passenger = MlPassenger {
54                            raw_text: line,
55                            index: line[0..4].parse::<u8>().ok(),
56                            group_count: line[7..8].parse::<u8>().ok(),
57                            passenger_name: &line[8..25],
58                            pnr_code: &line[25..31],
59                            flight_class: &line[31..33],
60                            action_code: &line[34..36],
61                            seat_count: line[36..39].parse::<u8>().ok(),
62                            office_code: &line[40..46],
63                            created_date: &line[47..54],
64                            passenger_info: &line[60..],
65                        };
66                        if let Some(passengers) = &mut seg.passengers {
67                            passengers.push(passenger);
68                        }
69                    }
70                } else {
71                    return Err(anyhow::Error::msg(
72                        "parse failed,passenger must has segment.".to_owned(),
73                    ));
74                }
75            }
76        }
77        Ok(mlinfo)
78    }
79}
80
81#[derive(Default, Debug)]
82pub struct MlSeg<'a> {
83    pub org: &'a str,
84    pub dst: &'a str,
85    pub passengers: Option<Vec<MlPassenger<'a>>>,
86}
87
88#[derive(Default, Debug)]
89pub struct MlPassenger<'a> {
90    pub index: Option<u8>,
91    pub group_count: Option<u8>,
92    pub passenger_name: &'a str,
93    pub pnr_code: &'a str,
94    pub flight_class: &'a str,
95    pub action_code: &'a str,
96    pub seat_count: Option<u8>,
97    pub office_code: &'a str,
98    pub created_date: &'a str,
99    pub passenger_info: &'a str,
100    pub raw_text: &'a str,
101}