use crate::directions::error::Error as DirectionsError;
use crate::error::Error as GoogleMapsError;
use phf::phf_map;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(u8)]
pub enum TransitMode {
#[default]
Bus = 0,
Rail = 1,
Subway = 2,
Train = 3,
Tram = 4,
}
impl<'de> Deserialize<'de> for TransitMode {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let string = String::deserialize(deserializer)?;
match Self::try_from(string.as_str()) {
Ok(variant) => Ok(variant),
Err(error) => Err(serde::de::Error::custom(error.to_string())),
} } }
impl Serialize for TransitMode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(std::convert::Into::<&str>::into(self))
} }
impl std::convert::From<&TransitMode> for &str {
fn from(transit_mode: &TransitMode) -> Self {
match transit_mode {
TransitMode::Bus => "bus",
TransitMode::Rail => "rail",
TransitMode::Subway => "subway",
TransitMode::Train => "train",
TransitMode::Tram => "tram",
} } }
impl std::fmt::Display for TransitMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", std::convert::Into::<&str>::into(self))
} }
impl std::convert::From<&TransitMode> for String {
fn from(transit_mode: &TransitMode) -> Self {
std::convert::Into::<&str>::into(transit_mode).to_string()
} }
impl std::convert::From<&Self> for TransitMode {
fn from(transit_mode: &Self) -> Self {
transit_mode.clone()
} }
static TRANSIT_MODES_BY_CODE: phf::Map<&'static str, TransitMode> = phf_map! {
"bus" => TransitMode::Bus,
"rail" => TransitMode::Rail,
"subway" => TransitMode::Subway,
"train" => TransitMode::Train,
"tram" => TransitMode::Tram,
};
impl std::convert::TryFrom<&str> for TransitMode {
type Error = GoogleMapsError;
fn try_from(transit_mode_code: &str) -> Result<Self, Self::Error> {
Ok(TRANSIT_MODES_BY_CODE
.get(transit_mode_code)
.cloned()
.ok_or_else(|| {
DirectionsError::InvalidTransitModeCode(transit_mode_code.to_string())
})?)
} }
impl std::str::FromStr for TransitMode {
type Err = GoogleMapsError;
fn from_str(transit_mode_code: &str) -> Result<Self, Self::Err> {
Ok(TRANSIT_MODES_BY_CODE
.get(transit_mode_code)
.cloned()
.ok_or_else(|| {
DirectionsError::InvalidTransitModeCode(transit_mode_code.to_string())
})?)
} }
impl TransitMode {
#[must_use]
pub const fn display(&self) -> &str {
match self {
Self::Bus => "Bus",
Self::Rail => "Rail",
Self::Subway => "Subway",
Self::Train => "Train",
Self::Tram => "Tram",
} } }