use std::{borrow::Cow, hash::Hash};
use serde::{Deserialize, Serialize};
use super::Component;
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ChannelAlias {
Stable,
Nightly(Option<Cow<'static, str>>),
#[serde(untagged)]
Tag(Cow<'static, str>),
}
impl<'de> serde::de::Deserialize<'de> for ChannelAlias {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Unexpected;
use serde_untagged::UntaggedEnumVisitor;
UntaggedEnumVisitor::new()
.string(|s| {
s.parse::<ChannelAlias>().map_err(|err| {
serde::de::Error::invalid_value(Unexpected::Str(s), &err.to_string().as_str())
})
})
.deserialize(deserializer)
}
}
impl core::str::FromStr for ChannelAlias {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"stable" => Ok(Self::Stable),
"nightly" => Ok(Self::Nightly(None)),
tag => match tag.strip_prefix("nightly-") {
Some(suffix) => Ok(Self::Nightly(Some(Cow::Owned(suffix.to_string())))),
None => Ok(Self::Tag(Cow::Owned(tag.to_string()))),
},
}
}
}
#[derive(Deserialize, Debug, Clone, Hash)]
#[serde(rename_all = "snake_case")]
pub enum Tags {
Partial,
Migration { old_channel: semver::Version },
}
#[derive(Deserialize, Debug, Clone, Hash)]
pub struct Channel {
pub name: semver::Version,
pub alias: Option<ChannelAlias>,
#[serde(default)]
pub tags: Vec<Tags>,
pub components: Vec<Component>,
}