use crate::registry::RecordId;
use core::fmt;
use indexmap::IndexSet;
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{str::FromStr, time::SystemTime};
use warg_crypto::hash::{AnyHash, HashAlgorithm};
use warg_crypto::signing;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PackageRecord {
pub prev: Option<RecordId>,
pub version: u32,
pub timestamp: SystemTime,
pub entries: Vec<PackageEntry>,
}
impl crate::Record for PackageRecord {
fn contents(&self) -> IndexSet<&AnyHash> {
self.entries
.iter()
.filter_map(PackageEntry::content)
.collect()
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub enum Permission {
Release,
Yank,
}
impl Permission {
pub const fn all() -> [Permission; 2] {
[Permission::Release, Permission::Yank]
}
}
impl fmt::Display for Permission {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Permission::Release => write!(f, "release"),
Permission::Yank => write!(f, "yank"),
}
}
}
impl FromStr for Permission {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"release" => Ok(Permission::Release),
"yank" => Ok(Permission::Yank),
_ => Err(format!("invalid permission {s:?}")),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum PackageEntry {
Init {
hash_algorithm: HashAlgorithm,
key: signing::PublicKey,
},
GrantFlat {
key: signing::PublicKey,
permissions: Vec<Permission>,
},
RevokeFlat {
key_id: signing::KeyID,
permissions: Vec<Permission>,
},
Release { version: Version, content: AnyHash },
Yank { version: Version },
}
impl PackageEntry {
pub fn required_permission(&self) -> Option<Permission> {
match self {
Self::Init { .. } | Self::GrantFlat { .. } | Self::RevokeFlat { .. } => None,
Self::Release { .. } => Some(Permission::Release),
Self::Yank { .. } => Some(Permission::Yank),
}
}
pub fn content(&self) -> Option<&AnyHash> {
match self {
Self::Release { content, .. } => Some(content),
_ => None,
}
}
}