use crate::{Arch, Artifact, Channel, Platform};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use url::Url;
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ReleaseInfo {
pub gui: ReleaseCollection,
pub cli: ReleaseCollection,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ReleaseCollection {
#[serde(flatten)]
pub channels: HashMap<Channel, PlatformRelease>,
}
impl ReleaseCollection {
pub fn find(
&self,
channel: &Channel,
platform: &Platform,
arch: &Arch,
) -> Option<&Artifact> {
if let Some(channel) = self.channels.get(channel) {
if let Some(releases) = channel.platforms.get(platform) {
releases.iter().find(|r| &r.arch == arch)
} else {
None
}
} else {
None
}
}
pub fn meta(&self, channel: &Channel) -> Option<&ReleaseMeta> {
if let Some(channel) = self.channels.get(channel) {
Some(&channel.meta)
} else {
None
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ReleaseNotes {
pub text: Url,
pub markdown: Url,
pub html: Url,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ReleaseMeta {
pub version: semver::Version,
pub notes: ReleaseNotes,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PlatformRelease {
pub meta: ReleaseMeta,
pub platforms: HashMap<Platform, Vec<Artifact>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Release {
artifact: Artifact,
}
#[cfg(test)]
mod test {
use super::*;
use crate::*;
use anyhow::Result;
use time::OffsetDateTime;
static JSON: &str = include_str!("releases.json");
#[test]
fn test_serde() -> Result<()> {
let mut info: ReleaseInfo = Default::default();
info.gui.channels.insert(
Channel::Beta,
PlatformRelease {
meta: ReleaseMeta {
version: "1.0.0".parse()?,
notes: ReleaseNotes {
text: "https://example.com".parse()?,
markdown: "https://example.com".parse()?,
html: "https://example.com".parse()?,
},
},
platforms: Default::default(),
},
);
info.gui
.channels
.get_mut(&Channel::Beta)
.unwrap()
.platforms
.insert(
Platform::Linux(Distro::Debian),
vec![Artifact {
platform: Platform::Linux(Distro::Debian),
name: String::new(),
sha256: vec![],
arch: Arch::X86_64,
commit: None,
timestamp: OffsetDateTime::now_utc(),
version: "1.0.0".parse()?,
artifact: None,
size: 0,
store: None,
}],
);
let json = serde_json::to_string_pretty(&info)?;
serde_json::from_str::<ReleaseInfo>(&json)?;
let info: ReleaseInfo = serde_json::from_str(JSON)?;
let artifact = &info.gui.find(
&Channel::Beta,
&Platform::MacOS,
&Arch::Universal,
);
assert!(artifact.is_some());
let artifact =
&info
.cli
.find(&Channel::Beta, &Platform::MacOS, &Arch::Aarch64);
assert!(artifact.is_some());
Ok(())
}
}