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())), 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}