airlabs_api/
lib.rs

1use std::collections::BTreeMap;
2
3use serde::Deserialize;
4use serde::Serialize;
5use serde::de::DeserializeOwned;
6
7pub use airlines::Airline;
8pub use airlines::AirlineFree;
9pub use airlines::AirlinesRequest;
10pub use airports::Airport;
11pub use airports::AirportFree;
12pub use airports::AirportsRequest;
13pub use error::Error;
14pub use flight::AircraftType;
15pub use flight::Flight;
16pub use flight::FlightCode;
17pub use flight::FlightFree;
18pub use flight::FlightRequest;
19pub use ping::PingRequest;
20pub use ping::Pong;
21pub use request::ClientInfo;
22pub use request::ConnectionInfo;
23pub use request::Karma;
24pub use request::Key;
25pub use request::Params;
26pub use request::Request;
27
28mod airlines;
29mod airports;
30mod error;
31mod flight;
32mod ping;
33mod request;
34
35/// Generic AirLabs API response shape.
36#[derive(Debug, Serialize, Deserialize)]
37pub struct Response<T> {
38    /// The request structure if present.
39    pub request: Option<Request>,
40    /// The actual response data, either a successful response or an error.
41    #[serde(flatten)]
42    pub result: ApiResult<T>,
43    /// Optional terms of service or disclaimer.
44    pub terms: Option<String>,
45}
46
47impl<T> Response<T> {
48    /// Converts the response into a idiomatic `Result`
49    pub fn into_result(self) -> Result<T, Error> {
50        self.result.into_result()
51    }
52
53    pub fn request(&self) -> Option<&Request> {
54        self.request.as_ref()
55    }
56
57    /// Similar to `Result::map` - applies map function to the successful response data.
58    pub fn map<U, F>(self, op: F) -> Response<U>
59    where
60        F: FnOnce(T) -> U,
61    {
62        Response {
63            request: self.request,
64            result: self.result.map(op),
65            terms: self.terms,
66        }
67    }
68}
69
70#[derive(Debug, Serialize, Deserialize)]
71#[serde(rename_all = "lowercase")]
72pub enum ApiResult<T> {
73    Response(T),
74    Error(Error),
75}
76
77impl<T> ApiResult<T> {
78    pub fn into_result(self) -> Result<T, Error> {
79        match self {
80            Self::Response(value) => Ok(value),
81            Self::Error(error) => Err(error),
82        }
83    }
84
85    pub fn map<U, F>(self, op: F) -> ApiResult<U>
86    where
87        F: FnOnce(T) -> U,
88    {
89        match self {
90            Self::Response(t) => ApiResult::Response(op(t)),
91            Self::Error(e) => ApiResult::Error(e),
92        }
93    }
94}
95
96/// For the AirLabs API request structure (that is serializable into query parameters)
97/// this trait captures the shape of the response, both its regular and free versions.
98pub trait AirLabsRequest: Serialize {
99    /// The shape of the regular response.
100    type Response: DeserializeOwned;
101    /// The shape of the free response.
102    type ResponseFree: DeserializeOwned;
103    /// The name of the API method.
104    const METHOD: &'static str;
105
106    /// Builds the URL for the API request.
107    fn url(&self, base: &str) -> String {
108        format!("{base}/{}", Self::METHOD)
109    }
110}
111
112fn default<T: Default>() -> T {
113    T::default()
114}