rustsim-modes 0.0.1

Shared multimodal mode semantics for rustsim: travel modes and compact allowed-mode sets
Documentation
//! Shared multimodal mode semantics for `rustsim`.
//!
//! This crate intentionally stays small and dependency-free so it can be
//! imported by any domain crate that needs common mode vocabulary.

#![deny(missing_docs)]

/// High-level travel mode used in multimodal simulations.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TravelMode {
    /// Movement on foot.
    Pedestrian,
    /// Private or shared road vehicle movement.
    Vehicle,
    /// Bicycle movement.
    Bicycle,
    /// Fixed-route public transit movement.
    Transit,
}

/// Compact permission set describing which travel modes are allowed.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct AllowedModes(u8);

impl AllowedModes {
    const PEDESTRIAN: u8 = 1 << 0;
    const VEHICLE: u8 = 1 << 1;
    const BICYCLE: u8 = 1 << 2;
    const TRANSIT: u8 = 1 << 3;

    /// No modes allowed.
    pub fn none() -> Self {
        Self(0)
    }

    /// All built-in modes allowed.
    pub fn all() -> Self {
        Self(Self::PEDESTRIAN | Self::VEHICLE | Self::BICYCLE | Self::TRANSIT)
    }

    /// Convenience set for pedestrian-only access.
    pub fn pedestrian_only() -> Self {
        Self(Self::PEDESTRIAN)
    }

    /// Convenience set for vehicle traffic, including transit.
    pub fn vehicular() -> Self {
        Self(Self::VEHICLE | Self::TRANSIT)
    }

    /// Convenience set for active mobility.
    pub fn active() -> Self {
        Self(Self::PEDESTRIAN | Self::BICYCLE)
    }

    /// Returns `true` if the given mode is allowed.
    pub fn allows(self, mode: TravelMode) -> bool {
        let flag = match mode {
            TravelMode::Pedestrian => Self::PEDESTRIAN,
            TravelMode::Vehicle => Self::VEHICLE,
            TravelMode::Bicycle => Self::BICYCLE,
            TravelMode::Transit => Self::TRANSIT,
        };
        self.0 & flag != 0
    }

    /// Return a copy with the given mode enabled.
    pub fn with_mode(mut self, mode: TravelMode) -> Self {
        let flag = match mode {
            TravelMode::Pedestrian => Self::PEDESTRIAN,
            TravelMode::Vehicle => Self::VEHICLE,
            TravelMode::Bicycle => Self::BICYCLE,
            TravelMode::Transit => Self::TRANSIT,
        };
        self.0 |= flag;
        self
    }
}

/// Convenience re-exports.
pub mod prelude {
    pub use crate::{AllowedModes, TravelMode};
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn allowed_modes_helpers_work() {
        let active = AllowedModes::active();
        assert!(active.allows(TravelMode::Pedestrian));
        assert!(active.allows(TravelMode::Bicycle));
        assert!(!active.allows(TravelMode::Vehicle));
        assert!(!active.allows(TravelMode::Transit));

        let custom = AllowedModes::none().with_mode(TravelMode::Transit);
        assert!(custom.allows(TravelMode::Transit));
        assert!(!custom.allows(TravelMode::Vehicle));
    }
}