Skip to main content

rustsim_modes/
lib.rs

1//! Shared multimodal mode semantics for `rustsim`.
2//!
3//! This crate intentionally stays small and dependency-free so it can be
4//! imported by any domain crate that needs common mode vocabulary.
5
6#![deny(missing_docs)]
7
8/// High-level travel mode used in multimodal simulations.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum TravelMode {
11    /// Movement on foot.
12    Pedestrian,
13    /// Private or shared road vehicle movement.
14    Vehicle,
15    /// Bicycle movement.
16    Bicycle,
17    /// Fixed-route public transit movement.
18    Transit,
19}
20
21/// Compact permission set describing which travel modes are allowed.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
23pub struct AllowedModes(u8);
24
25impl AllowedModes {
26    const PEDESTRIAN: u8 = 1 << 0;
27    const VEHICLE: u8 = 1 << 1;
28    const BICYCLE: u8 = 1 << 2;
29    const TRANSIT: u8 = 1 << 3;
30
31    /// No modes allowed.
32    pub fn none() -> Self {
33        Self(0)
34    }
35
36    /// All built-in modes allowed.
37    pub fn all() -> Self {
38        Self(Self::PEDESTRIAN | Self::VEHICLE | Self::BICYCLE | Self::TRANSIT)
39    }
40
41    /// Convenience set for pedestrian-only access.
42    pub fn pedestrian_only() -> Self {
43        Self(Self::PEDESTRIAN)
44    }
45
46    /// Convenience set for vehicle traffic, including transit.
47    pub fn vehicular() -> Self {
48        Self(Self::VEHICLE | Self::TRANSIT)
49    }
50
51    /// Convenience set for active mobility.
52    pub fn active() -> Self {
53        Self(Self::PEDESTRIAN | Self::BICYCLE)
54    }
55
56    /// Returns `true` if the given mode is allowed.
57    pub fn allows(self, mode: TravelMode) -> bool {
58        let flag = match mode {
59            TravelMode::Pedestrian => Self::PEDESTRIAN,
60            TravelMode::Vehicle => Self::VEHICLE,
61            TravelMode::Bicycle => Self::BICYCLE,
62            TravelMode::Transit => Self::TRANSIT,
63        };
64        self.0 & flag != 0
65    }
66
67    /// Return a copy with the given mode enabled.
68    pub fn with_mode(mut self, mode: TravelMode) -> Self {
69        let flag = match mode {
70            TravelMode::Pedestrian => Self::PEDESTRIAN,
71            TravelMode::Vehicle => Self::VEHICLE,
72            TravelMode::Bicycle => Self::BICYCLE,
73            TravelMode::Transit => Self::TRANSIT,
74        };
75        self.0 |= flag;
76        self
77    }
78}
79
80/// Convenience re-exports.
81pub mod prelude {
82    pub use crate::{AllowedModes, TravelMode};
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn allowed_modes_helpers_work() {
91        let active = AllowedModes::active();
92        assert!(active.allows(TravelMode::Pedestrian));
93        assert!(active.allows(TravelMode::Bicycle));
94        assert!(!active.allows(TravelMode::Vehicle));
95        assert!(!active.allows(TravelMode::Transit));
96
97        let custom = AllowedModes::none().with_mode(TravelMode::Transit);
98        assert!(custom.allows(TravelMode::Transit));
99        assert!(!custom.allows(TravelMode::Vehicle));
100    }
101}