use crate::{
error::Error,
rail::{client::responses, traits::NeedsLine},
requests::Fetch,
};
use serde::{
de::{Deserializer, Error as SerdeError},
Deserialize,
};
use std::{error, fmt, str::FromStr};
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Line {
Red,
Blue,
Yellow,
YellowLineRushPlus,
Orange,
Green,
Silver,
}
impl Fetch for Line {}
impl NeedsLine for Line {}
impl Line {
pub fn color(self) -> String {
match self {
Line::Red => "#4CAA61".to_string(),
Line::Blue => "#357ABB".to_string(),
Line::Yellow => "#F0CD4E".to_string(),
Line::Orange => "#4CAA61".to_string(),
Line::Green => "#4CAA61".to_string(),
Line::Silver => "#A4A6A3".to_string(),
Line::YellowLineRushPlus => "#F0CD4E".to_string(),
}
}
pub async fn stations(self, api_key: &str) -> Result<responses::Stations, Error> {
self.stations_on(Some(self), &api_key).await
}
}
impl<'de> Deserialize<'de> for Line {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let line = String::deserialize(deserializer)?;
Line::from_str(&line).map_err(|_| SerdeError::custom("String provided is not a Line code."))
}
}
impl ToString for Line {
fn to_string(&self) -> String {
match self {
Line::Red => "RD".to_string(),
Line::Blue => "BL".to_string(),
Line::Yellow => "YL".to_string(),
Line::Orange => "OR".to_string(),
Line::Green => "GR".to_string(),
Line::Silver => "SV".to_string(),
Line::YellowLineRushPlus => "YLRP".to_string(),
}
}
}
impl FromStr for Line {
type Err = StringIsNotLineError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"RD" => Ok(Line::Red),
"BL" => Ok(Line::Blue),
"YL" => Ok(Line::Yellow),
"OR" => Ok(Line::Orange),
"GR" => Ok(Line::Green),
"SV" => Ok(Line::Silver),
"YLRP" => Ok(Line::YellowLineRushPlus),
_ => Err(StringIsNotLineError),
}
}
}
#[derive(Debug, Clone)]
pub struct StringIsNotLineError;
impl fmt::Display for StringIsNotLineError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Provided string is not a valid line code.")
}
}
impl error::Error for StringIsNotLineError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
None
}
}