gatelogue_types/node/
mod.rs

1pub mod air;
2pub mod bus;
3pub mod located;
4pub mod rail;
5pub mod sea;
6pub mod spawn_warp;
7pub mod town;
8
9use enum_dispatch::enum_dispatch;
10use rusqlite::OptionalExtension;
11use strum_macros::{EnumIs, EnumTryAs};
12
13use crate::{
14    error::Result,
15    node::{
16        air::{AirAirline, AirAirport, AirFlight, AirGate},
17        bus::{BusBerth, BusCompany, BusConnection, BusLine, BusStop},
18        located::AnyLocatedNode,
19        rail::{RailCompany, RailConnection, RailLine, RailPlatform, RailStation},
20        sea::{SeaCompany, SeaConnection, SeaDock, SeaLine, SeaStop},
21        spawn_warp::SpawnWarp,
22        town::Town,
23    },
24    util::ID,
25    GD,
26};
27
28#[enum_dispatch]
29pub trait Node: Copy {
30    fn i(self) -> ID;
31    fn ty(self) -> &'static str;
32}
33
34#[enum_dispatch(Node)]
35#[derive(Clone, Copy, PartialEq, Eq, Debug, EnumIs, EnumTryAs)]
36pub enum AnyNode {
37    AirAirline,
38    AirAirport,
39    AirGate,
40    AirFlight,
41    BusCompany,
42    BusLine,
43    BusStop,
44    BusBerth,
45    BusConnection,
46    RailCompany,
47    RailLine,
48    RailStation,
49    RailPlatform,
50    RailConnection,
51    SeaCompany,
52    SeaLine,
53    SeaStop,
54    SeaDock,
55    SeaConnection,
56    SpawnWarp,
57    Town,
58}
59macro_rules! impl_any_node {
60    ($($Variant:ident),+) => {
61        impl AnyNode {
62            pub fn from_id(gd: &GD, id: ID) -> Result<Option<Self>> {
63                gd.0.query_one("SELECT type FROM Node WHERE i = ?", (id,), |row| {
64                    Ok(match &*row.get::<_, String>(0)? {
65                        $(stringify!($Variant) => $Variant(id).into(),)+
66                        _ => unreachable!(),
67                    })
68                }).optional().map_err(Into::into)
69            }
70        }
71    };
72}
73impl_any_node!(
74    AirAirline,
75    AirAirport,
76    AirGate,
77    AirFlight,
78    BusCompany,
79    BusLine,
80    BusStop,
81    BusBerth,
82    BusConnection,
83    RailCompany,
84    RailLine,
85    RailStation,
86    RailPlatform,
87    RailConnection,
88    SeaCompany,
89    SeaLine,
90    SeaStop,
91    SeaDock,
92    SeaConnection,
93    SpawnWarp,
94    Town
95);
96
97#[macro_export]
98macro_rules! node_type {
99    ($Ty:ident) => {
100        #[derive(Clone, Copy, PartialEq, Eq, Debug)]
101        pub struct $Ty(pub(crate) ID);
102
103        impl $crate::node::Node for $Ty {
104            fn i(self) -> ID {
105                self.0
106            }
107            fn ty(self) -> &'static str {
108                stringify!($Ty)
109            }
110        }
111
112        impl From<ID> for $Ty {
113            fn from(value: ID) -> Self {
114                Self(value)
115            }
116        }
117
118        impl rusqlite::types::FromSql for $Ty {
119            fn column_result(
120                value: rusqlite::types::ValueRef<'_>,
121            ) -> rusqlite::types::FromSqlResult<Self> {
122                Ok(Self(ID::try_from(value.as_i64()?).map_err(|e| {
123                    rusqlite::types::FromSqlError::Other(e.into())
124                })?))
125            }
126        }
127    };
128
129    (located $Ty:ident) => {
130        node_type!($Ty);
131
132        impl $crate::node::located::LocatedNode for $Ty {}
133    };
134}