use chrono;
use collections;
use serde;
use url_serde;
impl serde::Serialize for super::Channel {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[derive(Serialize)]
struct EncodedChannel<'a> {
#[serde(rename = "manifest-version")]
manifest_version: &'a str,
date: &'a chrono::naive::NaiveDate,
#[serde(
skip_serializing_if = "::std::collections::BTreeMap::is_empty"
)]
pkg: &'a collections::BTreeMap<String, super::Package>,
#[serde(
skip_serializing_if = "::std::collections::BTreeMap::is_empty"
)]
renames: collections::BTreeMap<
&'a str,
collections::BTreeMap<&'a str, &'a str>,
>,
}
let mut fake_renames = collections::BTreeMap::new();
for (old_pkg, new_pkg) in self.renames.iter() {
let mut inner = collections::BTreeMap::new();
inner.insert("to", new_pkg.as_str());
fake_renames.insert(old_pkg.as_str(), inner);
}
let output = EncodedChannel {
manifest_version: "2",
date: &self.date,
pkg: &self.pkg,
renames: fake_renames,
};
output.serialize(serializer)
}
}
impl<'de> serde::Deserialize<'de> for super::Channel {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
#[derive(Deserialize)]
#[serde(tag = "manifest-version")]
enum EncodedChannel {
#[serde(rename = "2")]
VersionTwo {
date: chrono::naive::NaiveDate,
#[serde(default)]
pkg: collections::BTreeMap<String, super::Package>,
#[serde(default)]
renames: collections::BTreeMap<
String,
collections::BTreeMap<String, String>,
>,
},
}
match EncodedChannel::deserialize(deserializer)? {
EncodedChannel::VersionTwo { date, pkg, renames } => {
let mut fixed_renames = collections::BTreeMap::new();
for (old_pkg, mut inner_map) in renames {
let new_pkg = inner_map
.remove("to")
.ok_or(D::Error::missing_field("to"))?;
fixed_renames.insert(old_pkg, new_pkg);
}
Ok(super::Channel {
date: date,
pkg: pkg,
renames: fixed_renames,
})
}
}
}
}
impl serde::Serialize for super::Artefact {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
fn slice_is_empty<T>(s: &[T]) -> bool {
s.is_empty()
}
#[derive(Serialize, Default, Debug)]
struct EncodedArtefact<'a> {
available: bool,
url: Option<url_serde::SerdeUrl>,
hash: Option<&'a str>,
xz_url: Option<url_serde::SerdeUrl>,
xz_hash: Option<&'a str>,
#[serde(skip_serializing_if = "slice_is_empty")]
components: &'a [super::ArtefactToken],
#[serde(skip_serializing_if = "slice_is_empty")]
extensions: &'a [super::ArtefactToken],
}
let mut output = EncodedArtefact::default();
output.available = !self.standalone.is_empty();
self.standalone
.get(&super::ArchiveFormat::TarGzip)
.map(|src| {
output.url = Some(url_serde::Serde(src.url.clone()));
output.hash = Some(&src.hash);
});
self.standalone
.get(&super::ArchiveFormat::TarXz)
.map(|src| {
output.xz_url = Some(url_serde::Serde(src.url.clone()));
output.xz_hash = Some(&src.hash);
});
output.components = &self.components;
output.extensions = &self.extensions;
output.serialize(serializer)
}
}
impl<'de> serde::Deserialize<'de> for super::Artefact {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(Deserialize, Debug)]
struct EncodedArtefact {
available: bool,
url: Option<url_serde::SerdeUrl>,
hash: Option<String>,
xz_url: Option<url_serde::SerdeUrl>,
xz_hash: Option<String>,
#[serde(default)]
components: Vec<super::ArtefactToken>,
#[serde(default)]
extensions: Vec<super::ArtefactToken>,
}
let input = EncodedArtefact::deserialize(deserializer)?;
let mut output = super::Artefact::default();
if let (Some(url), Some(hash)) = (input.url, input.hash) {
output.standalone.insert(
super::ArchiveFormat::TarGzip,
super::ArchiveSource::new(url.into_inner(), hash),
);
}
if let (Some(url), Some(hash)) = (input.xz_url, input.xz_hash) {
output.standalone.insert(
super::ArchiveFormat::TarXz,
super::ArchiveSource::new(url.into_inner(), hash),
);
}
output.components = input.components;
output.extensions = input.extensions;
Ok(output)
}
}