warg_protocol/package/
model.rs1use crate::registry::RecordId;
2use core::fmt;
3use indexmap::IndexSet;
4use semver::Version;
5use serde::{Deserialize, Serialize};
6use std::{str::FromStr, time::SystemTime};
7use warg_crypto::hash::{AnyHash, HashAlgorithm};
8use warg_crypto::signing;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct PackageRecord {
13 pub prev: Option<RecordId>,
15 pub version: u32,
17 pub timestamp: SystemTime,
19 pub entries: Vec<PackageEntry>,
21}
22
23impl crate::Record for PackageRecord {
24 fn contents(&self) -> IndexSet<&AnyHash> {
25 self.entries
26 .iter()
27 .filter_map(PackageEntry::content)
28 .collect()
29 }
30}
31
32#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35#[non_exhaustive]
36pub enum Permission {
37 Release,
38 Yank,
39}
40
41impl Permission {
42 pub const fn all() -> [Permission; 2] {
44 [Permission::Release, Permission::Yank]
45 }
46}
47
48impl fmt::Display for Permission {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 match self {
51 Permission::Release => write!(f, "release"),
52 Permission::Yank => write!(f, "yank"),
53 }
54 }
55}
56
57impl FromStr for Permission {
58 type Err = String;
59
60 fn from_str(s: &str) -> Result<Self, Self::Err> {
61 match s {
62 "release" => Ok(Permission::Release),
63 "yank" => Ok(Permission::Yank),
64 _ => Err(format!("invalid permission {s:?}")),
65 }
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70#[non_exhaustive]
71pub enum PackageEntry {
72 Init {
75 hash_algorithm: HashAlgorithm,
77 key: signing::PublicKey,
79 },
80 GrantFlat {
83 key: signing::PublicKey,
84 permissions: Vec<Permission>,
85 },
86 RevokeFlat {
89 key_id: signing::KeyID,
90 permissions: Vec<Permission>,
91 },
92 Release { version: Version, content: AnyHash },
95 Yank { version: Version },
98}
99
100impl PackageEntry {
101 pub fn required_permission(&self) -> Option<Permission> {
103 match self {
104 Self::Init { .. } | Self::GrantFlat { .. } | Self::RevokeFlat { .. } => None,
105 Self::Release { .. } => Some(Permission::Release),
106 Self::Yank { .. } => Some(Permission::Yank),
107 }
108 }
109
110 pub fn content(&self) -> Option<&AnyHash> {
114 match self {
115 Self::Release { content, .. } => Some(content),
116 _ => None,
117 }
118 }
119}