mod channel;
mod component;
pub mod unknown;
use std::path::Path;
use serde::{Deserialize, Serialize};
pub use self::{channel::*, component::*, unknown::*};
use super::ManifestError;
pub const MANIFEST_VERSION: semver::Version = semver::Version::new(2, 0, 0);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Manifest {
pub(super) manifest_version: semver::Version,
pub(super) date: i64,
pub(super) channels: Vec<Channel>,
#[serde(flatten)]
pub(super) extra: Extra,
}
impl Manifest {
pub fn load_from_file(path: impl AsRef<Path>) -> Result<Self, ManifestError> {
let path = path.as_ref();
let manifest_contents = std::fs::read_to_string(path)
.map_err(|_| ManifestError::Missing(path.display().to_string()))?;
if manifest_contents.is_empty() {
return Err(ManifestError::Empty);
}
Self::parse_str(&manifest_contents)
}
pub fn parse_str(content: &str) -> Result<Self, ManifestError> {
let mut manifest = serde_json::from_str::<Self>(content)
.map_err(|err| ManifestError::Invalid(format!("failed to parse manifest: {err}")))?;
if manifest.manifest_version.major != MANIFEST_VERSION.major {
return Err(ManifestError::UnsupportedVersion(manifest.manifest_version));
}
if !manifest.channels.is_sorted_by_key(|channel| &channel.name) {
manifest.channels.sort_by_key(|channel| channel.name.clone());
};
for channel in manifest.channels.iter_mut() {
if !channel.components.is_sorted_by_key(|c| c.name.as_ref()) {
channel.components.sort_by_key(|c| c.name.clone());
}
}
Ok(manifest)
}
}
impl Default for Manifest {
fn default() -> Self {
let date = chrono::Utc::now().timestamp();
Self {
manifest_version: MANIFEST_VERSION,
date,
channels: vec![],
extra: Extra::new(),
}
}
}
impl Manifest {
#[inline(always)]
pub fn manifest_version(&self) -> &semver::Version {
&self.manifest_version
}
}