1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
5#[serde(rename_all = "lowercase")]
6pub enum ArtifactIdentity {
7 #[default]
8 Auto,
9 Man,
10}
11
12impl ArtifactIdentity {
13 pub const fn code(self) -> &'static str {
14 match self {
15 Self::Auto => "auto",
16 Self::Man => "man",
17 }
18 }
19 pub fn from_code(value: &str) -> Result<Self, crate::ArtifactReferenceError> {
20 match value {
21 "auto" => Ok(Self::Auto),
22 "man" => Ok(Self::Man),
23 _ => Err(crate::invalid("unsupported artifact identity")),
24 }
25 }
26 pub fn validate_creation_id(
28 self,
29 id: Option<&str>,
30 ) -> Result<(), crate::ArtifactReferenceError> {
31 match (self, id) {
32 (Self::Man, Some(id)) if !id.is_empty() && id.len() <= 128
33 && id.bytes().all(|b| b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_')) => Ok(()),
34 (Self::Man, _) => Err(crate::invalid("man identity requires a caller-supplied creation ID of 1-128 ASCII letters, digits, hyphens or underscores")),
35 (Self::Auto, None) => Ok(()),
36 (Self::Auto, Some(_)) => Err(crate::invalid("creation ID requires man identity")),
37 }
38 }
39}
40
41#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
43#[serde(rename_all = "lowercase")]
44pub enum ArtifactRetention {
45 #[default]
46 Std,
47 Tmp,
48}
49
50impl ArtifactRetention {
51 pub const fn code(self) -> &'static str {
52 match self {
53 Self::Std => "std",
54 Self::Tmp => "tmp",
55 }
56 }
57 pub const fn is_temporary(self) -> bool {
58 matches!(self, Self::Tmp)
59 }
60 pub fn from_code(value: &str) -> Result<Self, crate::ArtifactReferenceError> {
61 match value {
62 "std" => Ok(Self::Std),
63 "tmp" => Ok(Self::Tmp),
64 _ => Err(crate::invalid("unsupported artifact retention")),
65 }
66 }
67}
68
69#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
71#[serde(deny_unknown_fields)]
72pub struct ArtifactPolicy {
73 pub identity: ArtifactIdentity,
74 pub retention: ArtifactRetention,
75}
76
77impl ArtifactPolicy {
78 pub const AUTO_STD: Self = Self::new(ArtifactIdentity::Auto, ArtifactRetention::Std);
79 pub const AUTO_TMP: Self = Self::new(ArtifactIdentity::Auto, ArtifactRetention::Tmp);
80 pub const MAN_STD: Self = Self::new(ArtifactIdentity::Man, ArtifactRetention::Std);
81 pub const MAN_TMP: Self = Self::new(ArtifactIdentity::Man, ArtifactRetention::Tmp);
82 pub const fn new(identity: ArtifactIdentity, retention: ArtifactRetention) -> Self {
83 Self {
84 identity,
85 retention,
86 }
87 }
88 pub const fn is_temporary(self) -> bool {
89 self.retention.is_temporary()
90 }
91 pub fn validate_creation_id(
92 self,
93 id: Option<&str>,
94 ) -> Result<(), crate::ArtifactReferenceError> {
95 self.identity.validate_creation_id(id)
96 }
97}