Skip to main content

artifact_api/
lifecycle.rs

1use serde::{Deserialize, Serialize};
2
3/// Retention and ownership policy; part of resource identity, never the content digest.
4#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
5#[serde(rename_all = "lowercase")]
6pub enum ArtifactLifecycle {
7    #[default]
8    Std,
9    Tmp,
10    Man,
11}
12
13impl ArtifactLifecycle {
14    pub const fn code(self) -> &'static str {
15        match self {
16            Self::Std => "std",
17            Self::Tmp => "tmp",
18            Self::Man => "man",
19        }
20    }
21
22    pub const fn is_temporary(self) -> bool {
23        matches!(self, Self::Tmp)
24    }
25
26    pub fn from_code(value: &str) -> Result<Self, crate::ArtifactReferenceError> {
27        match value {
28            "std" => Ok(Self::Std),
29            "tmp" => Ok(Self::Tmp),
30            "man" => Ok(Self::Man),
31            _ => Err(crate::invalid("unsupported artifact lifecycle")),
32        }
33    }
34
35    /// Manual callers may reserve a 128-bit creation ID for retry/recovery before uploading.
36    pub fn validate_creation_id(
37        self,
38        id: Option<&str>,
39    ) -> Result<(), crate::ArtifactReferenceError> {
40        if let Some(id) = id {
41            if self != Self::Man
42                || id.len() != 32
43                || !id
44                    .bytes()
45                    .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
46            {
47                return Err(crate::invalid(
48                    "creation ID must be 32 lowercase hex characters and requires man lifecycle",
49                ));
50            }
51        }
52        Ok(())
53    }
54}