eterm_parser/
pat.rs

1use crate::util;
2
3#[derive(Default, Debug)]
4pub struct Pat<'a> {
5    pub raw_text: &'a str,
6    pub items: Option<Vec<PatItem<'a>>>,
7}
8
9impl<'a> Pat<'a> {
10    pub fn parse(text: &'a str) -> anyhow::Result<Self> {
11        if text.is_empty() {
12            return Err(anyhow::Error::msg(
13                "pnr parameter shouldn't be empty.".to_owned(),
14            ));
15        }
16        let re = regex::Regex::new(
17            r"(?<INDEX>\d+)\s+(?<SEATCLASS>[/\w+]+)\s+FARE:(?<FARE>[\w.]+)\s+TAX:(?<TAX>[\w.]+)\s+YQ:(?<YQ>[\w.]+)\s+TOTAL:(?<TOTAL>[\w.]+)",
18        )?;
19
20        let pat = Self {
21            raw_text: text,
22            items: Some(
23                re.captures_iter(text)
24                    .filter_map(|caps| {
25                        match (
26                            caps.name("INDEX"),
27                            caps.name("SEATCLASS"),
28                            caps.name("FARE"),
29                            caps.name("TAX"),
30                            caps.name("YQ"),
31                            caps.name("TOTAL"),
32                        ) {
33                            (index, seatclass, fare, tax, yq, total) => Some(PatItem {
34                                index: util::regex_extact_value::<u8>(index),
35                                seat_class: seatclass.and_then(|x| Some(x.as_str().trim())), // crate::regex_extact_text(seatclass),
36                                fare: fare.and_then(|x| PatPrice::parse(x.as_str()).ok()),
37                                tax: tax.and_then(|x| PatPrice::parse(x.as_str()).ok()),
38                                yq: yq.and_then(|x| PatPrice::parse(x.as_str()).ok()),
39                                total: util::regex_extact_value::<f32>(total),
40                                raw_text: caps.get(0).and_then(|x| Some(x.as_str())),
41                            }),
42                        }
43                    })
44                    .collect::<Vec<_>>(),
45            ),
46        };
47        return Ok(pat);
48    }
49}
50
51#[derive(Default, Debug)]
52pub struct PatItem<'a> {
53    pub index: Option<u8>,
54    pub seat_class: Option<&'a str>,
55    pub fare: Option<PatPrice<'a>>,
56    pub tax: Option<PatPrice<'a>>,
57    pub yq: Option<PatPrice<'a>>,
58    pub total: Option<f32>,
59    pub raw_text: Option<&'a str>,
60}
61
62#[derive(Default, Debug, PartialEq)]
63pub struct PatPrice<'a> {
64    pub currency: Option<&'a str>,
65    pub price: Option<f32>,
66    pub is_exemption: bool,
67}
68
69impl<'a> PatPrice<'a> {
70    pub fn parse(text: &'a str) -> anyhow::Result<Self> {
71        let mut pat_price = Self {
72            ..Default::default()
73        };
74        let tx = text.trim();
75        if tx.to_uppercase().starts_with("TEXEMPT") {
76            pat_price.price = Some(0f32);
77            pat_price.is_exemption = true;
78        } else {
79            pat_price.currency = Some(&tx[0..3]);
80            pat_price.price = tx[3..].parse::<f32>().ok();
81            pat_price.is_exemption = false;
82        }
83        Ok(pat_price)
84    }
85}