Skip to main content

flyr/
proto.rs

1use crate::query::{FlightLeg, Passengers, Seat, TripType};
2
3fn encode_varint(mut value: u64, buf: &mut Vec<u8>) {
4    loop {
5        let byte = (value & 0x7F) as u8;
6        value >>= 7;
7        if value == 0 {
8            buf.push(byte);
9            break;
10        }
11        buf.push(byte | 0x80);
12    }
13}
14
15fn encode_tag(field: u32, wire_type: u8, buf: &mut Vec<u8>) {
16    encode_varint(((field as u64) << 3) | wire_type as u64, buf);
17}
18
19fn encode_string(field: u32, s: &str, buf: &mut Vec<u8>) {
20    encode_tag(field, 2, buf);
21    encode_varint(s.len() as u64, buf);
22    buf.extend_from_slice(s.as_bytes());
23}
24
25fn encode_submessage(field: u32, inner: &[u8], buf: &mut Vec<u8>) {
26    encode_tag(field, 2, buf);
27    encode_varint(inner.len() as u64, buf);
28    buf.extend_from_slice(inner);
29}
30
31fn encode_airport(code: &str) -> Vec<u8> {
32    let mut buf = Vec::new();
33    encode_string(2, code, &mut buf);
34    buf
35}
36
37fn encode_flight_data(leg: &FlightLeg) -> Vec<u8> {
38    let mut buf = Vec::new();
39
40    encode_string(2, &leg.date, &mut buf);
41
42    if let Some(max_stops) = leg.max_stops {
43        encode_tag(5, 0, &mut buf);
44        encode_varint(max_stops as u64, &mut buf);
45    }
46
47    if let Some(ref airlines) = leg.airlines {
48        for airline in airlines {
49            encode_string(6, airline, &mut buf);
50        }
51    }
52
53    let from = encode_airport(&leg.from_airport);
54    encode_submessage(13, &from, &mut buf);
55
56    let to = encode_airport(&leg.to_airport);
57    encode_submessage(14, &to, &mut buf);
58
59    buf
60}
61
62fn seat_to_varint(seat: &Seat) -> u64 {
63    match seat {
64        Seat::Economy => 1,
65        Seat::PremiumEconomy => 2,
66        Seat::Business => 3,
67        Seat::First => 4,
68    }
69}
70
71fn trip_to_varint(trip: &TripType) -> u64 {
72    match trip {
73        TripType::RoundTrip => 1,
74        TripType::OneWay => 2,
75        TripType::MultiCity => 3,
76    }
77}
78
79fn passengers_to_enums(p: &Passengers) -> Vec<u64> {
80    let mut vals = Vec::new();
81    vals.extend(std::iter::repeat_n(1, p.adults as usize));
82    vals.extend(std::iter::repeat_n(2, p.children as usize));
83    vals.extend(std::iter::repeat_n(3, p.infants_in_seat as usize));
84    vals.extend(std::iter::repeat_n(4, p.infants_on_lap as usize));
85    vals
86}
87
88pub fn encode(
89    legs: &[FlightLeg],
90    passengers: &Passengers,
91    seat: &Seat,
92    trip: &TripType,
93) -> Vec<u8> {
94    let mut buf = Vec::new();
95
96    for leg in legs {
97        let fd = encode_flight_data(leg);
98        encode_submessage(3, &fd, &mut buf);
99    }
100
101    let pax = passengers_to_enums(passengers);
102    if !pax.is_empty() {
103        let mut packed = Vec::new();
104        for v in &pax {
105            encode_varint(*v, &mut packed);
106        }
107        encode_tag(8, 2, &mut buf);
108        encode_varint(packed.len() as u64, &mut buf);
109        buf.extend_from_slice(&packed);
110    }
111
112    encode_tag(9, 0, &mut buf);
113    encode_varint(seat_to_varint(seat), &mut buf);
114
115    encode_tag(19, 0, &mut buf);
116    encode_varint(trip_to_varint(trip), &mut buf);
117
118    buf
119}