//! Decoding the actual inner decrypted payload bit. use crate::{slice_base64, slice_bool}; use anyhow::anyhow; use bitvec::field::BitField; use bitvec::order::Msb0; use bitvec::slice::BitSlice; use bitvec::view::BitView; use time::macros::datetime; use time::{Date, Duration, PrimitiveDateTime, Time}; #[derive(Copy, Clone, Debug)] pub enum CouponType { Single = 0, Season = 1, ReturnOutbound = 2, ReturnInbound = 3, } #[derive(Clone, Debug)] pub struct TicketPurchaseDetails { pub purchase_time: PrimitiveDateTime, pub price_pence: u32, pub purchase_reference: Option, pub days_of_validity: u16, } #[derive(Clone, Debug)] pub struct Reservation { pub retail_service_id: String, pub coach: char, pub seat_number: u8, pub seat_letter: Option, } impl Reservation { pub fn decode(resv: &BitSlice) -> anyhow::Result { if resv.len() != 45 { return Err(anyhow!("reservation length {}, not 45", resv.len())); } let rsid_1 = char::from(resv[0..6].load_be::() + 32); let rsid_2 = char::from(resv[6..12].load_be::() + 32); let rsid_nums: u16 = resv[12..26].load_be(); let retail_service_id = format!("{}{}{:04}", rsid_1, rsid_2, rsid_nums); let coach = char::from(resv[26..32].load_be::() + 32); let seat_letter = char::from(resv[32..38].load_be::() + 32); let seat_letter = (seat_letter != ' ').then_some(seat_letter); let seat_number: u8 = resv[38..45].load_be(); Ok(Self { retail_service_id, coach, seat_number, seat_letter, }) } } #[derive(Clone, Debug)] pub struct Rsp6Ticket { pub manually_inspect: bool, pub ticket_reference: String, pub checksum: char, pub version: u8, pub standard_class: bool, pub lennon_ticket_type: String, pub fare: String, pub origin_nlc: String, pub destination_nlc: String, pub retailer_id: String, pub child_ticket: bool, pub coupon_type: CouponType, pub discount_code: u16, pub route_code: u32, pub start_date: Date, pub depart_time: Option