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(®ex::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}