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}