gatelogue-types 3.1.3+13

Types for loading and reading Gatelogue data
Documentation
use rusqlite::types::{FromSql, FromSqlResult, ValueRef};
use strum_macros::EnumString;

use crate::{_from_sql_for_enum, _get_column, _get_derived_vec, _get_set, node_type, util::ID};

#[derive(Clone, Copy, PartialEq, Eq, Debug, EnumString)]
pub enum AirMode {
    #[strum(serialize = "helicopter")]
    Helicopter,
    #[strum(serialize = "seaplane")]
    Seaplane,
    #[strum(serialize = "warp plane")]
    WarpPlane,
    #[strum(serialize = "traincarts plane")]
    TrainCartsPlane,
}
_from_sql_for_enum!(AirMode);

node_type!(AirAirline);
impl AirAirline {
    _get_column!("AirAirline", name, String);
    _get_column!("AirAirline", link, Option<String>);

    _get_derived_vec!(flights, AirFlight, "../sql/air/airline_flights.sql");
    _get_derived_vec!(gates, AirGate, "../sql/air/airline_gates.sql");
    _get_derived_vec!(airports, AirAirport, "../sql/air/airline_airports.sql");
}

node_type!(located AirAirport);
impl AirAirport {
    _get_column!("AirAirport", code, String);
    _get_set!("AirAirportNames", names, "name", String);
    _get_column!("AirAirport", link, Option<String>);
    _get_set!("AirAirportModes", modes, "mode", AirMode);
    _get_derived_vec!(gates, AirGate, "../sql/air/airport_gates.sql");
}

node_type!(AirGate);
impl AirGate {
    _get_column!("AirGate", code, Option<String>);
    _get_column!("AirGate", airport, AirAirport);
    _get_column!("AirGate", airline, Option<AirAirline>);
    _get_column!("AirGate", width, Option<u32>);
    _get_column!("AirGate", mode, AirMode);
    _get_derived_vec!(
        flights_from_here,
        AirFlight,
        "../sql/air/gate_flights_from_here.sql"
    );
    _get_derived_vec!(
        flights_to_here,
        AirFlight,
        "../sql/air/gate_flights_to_here.sql"
    );
}

node_type!(AirFlight);
impl AirFlight {
    _get_column!("AirFlight", airline, AirAirline);
    _get_column!("AirFlight", code, String);
    _get_column!("AirFlight", from, AirGate);
    _get_column!("AirFlight", to, AirGate);
    _get_column!("AirFlight", aircraft, Option<Aircraft>);
    _get_column!("AirFlight", duration, Option<u32>);
}

#[macro_export]
macro_rules! get_aircraft_column {
    ($column_name:ident, $ColTy:ty) => {
        pub fn $column_name(self, gd: &$crate::GD) -> $crate::error::Result<$ColTy> {
            gd.0.query_one(
                concat!(
                    "SELECT \"",
                    stringify!($column_name),
                    "\" FROM Aircraft WHERE name = ?"
                ),
                (&self.name(),),
                |a| a.get(0),
            )
            .map_err(|e| {
                if e == rusqlite::Error::QueryReturnedNoRows {
                    $crate::error::Error::NoAircraft(self.name().clone())
                } else {
                    e.into()
                }
            })
        }
    };
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Aircraft(pub(crate) String);
impl FromSql for Aircraft {
    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
        Ok(Self(value.as_str()?.into()))
    }
}

impl Aircraft {
    #[must_use]
    pub const fn name(&self) -> &String {
        &self.0
    }
    get_aircraft_column!(manufacturer, String);
    get_aircraft_column!(width, u32);
    get_aircraft_column!(height, u32);
    get_aircraft_column!(length, u32);
    get_aircraft_column!(mode, AirMode);
}