use chrono::{Date, TimeZone, Utc};
use serde::Serializer;
use std::fmt::{Display, Formatter};
#[derive(Debug, Copy, Clone, Serialize)]
pub enum Channel {
Stable,
Beta,
Nightly,
Version {
major: u32,
minor: u32,
patch: Option<u32>,
},
}
impl Display for Channel {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Channel::Stable => {
write!(f, "stable")
}
Channel::Beta => {
write!(f, "beta")
}
Channel::Nightly => {
write!(f, "nightly")
}
Channel::Version {
major,
minor,
patch,
} => match patch {
None => {
write!(f, "{}.{}", major, minor)
}
Some(patch) => {
write!(f, "{}.{}.{}", major, minor, patch)
}
},
}
}
}
#[derive(Debug, Serialize, Clone)]
pub struct Toolchain {
pub channel: Channel,
#[serde(serialize_with = "serialize_date")]
pub date: Option<Date<Utc>>,
pub target_triple: Option<String>,
}
fn serialize_date<S>(date: &Option<Date<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match date {
None => serializer.serialize_none(),
Some(s) => {
let date = s.format("%f").to_string();
serializer.serialize_some(&date)
}
}
}
impl Toolchain {
pub fn with_channel(channel: Channel) -> Self {
Self {
channel,
date: None,
target_triple: None,
}
}
pub fn with_version(major: u32, minor: u32) -> Self {
Self {
channel: Channel::Version {
major,
minor,
patch: None,
},
date: None,
target_triple: None,
}
}
pub fn stable() -> Self {
Self::with_channel(Channel::Stable)
}
pub fn nightly() -> Self {
Self::with_channel(Channel::Nightly)
}
pub fn dated_nightly<Tz: TimeZone>(date: Date<Tz>) -> Self {
let mut toolchain = Self::with_channel(Channel::Nightly);
toolchain.date = Some(date.with_timezone(&Utc));
toolchain
}
}
impl Display for Toolchain {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}{}{}",
self.channel,
self.date
.as_ref()
.map(|date| { format!("-{}", date.format("%F")) })
.unwrap_or_default(),
self.target_triple
.as_ref()
.map(|s| format!("-{}", s))
.unwrap_or_default()
)
}
}