Skip to main content

sigstore_types/
artifact.rs

1//! Artifact types for signing and verification
2//!
3//! This module provides types for representing artifacts to be signed or verified.
4//! Artifacts can be provided as raw bytes or as pre-computed digests, allowing
5//! for efficient handling of large files without loading them entirely into memory.
6
7use crate::Sha256Hash;
8
9/// An artifact to be signed or verified
10///
11/// This enum allows flexible input for signing and verification operations:
12/// - `Bytes`: Raw artifact bytes (hash will be computed internally)
13/// - `Digest`: Pre-computed SHA-256 digest (no raw bytes needed)
14///
15/// # Example
16///
17/// ```
18/// use sigstore_types::{Artifact, Sha256Hash};
19///
20/// // From raw bytes
21/// let artifact = Artifact::from(b"hello world".as_slice());
22///
23/// // From pre-computed digest
24/// let digest = Sha256Hash::from_hex(
25///     "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
26/// ).unwrap();
27/// let artifact = Artifact::from(digest);
28/// ```
29#[derive(Debug, Clone)]
30pub enum Artifact<'a> {
31    /// Raw artifact bytes (hash will be computed)
32    Bytes(&'a [u8]),
33    /// Pre-computed SHA-256 digest
34    Digest(Sha256Hash),
35}
36
37impl<'a> Artifact<'a> {
38    /// Create an artifact from raw bytes
39    pub fn from_bytes(bytes: &'a [u8]) -> Self {
40        Artifact::Bytes(bytes)
41    }
42
43    /// Create an artifact from a pre-computed digest
44    pub fn from_digest(digest: Sha256Hash) -> Self {
45        Artifact::Digest(digest)
46    }
47
48    /// Check if this artifact has raw bytes available
49    pub fn has_bytes(&self) -> bool {
50        matches!(self, Artifact::Bytes(_))
51    }
52
53    /// Get the raw bytes if available
54    pub fn bytes(&self) -> Option<&[u8]> {
55        match self {
56            Artifact::Bytes(bytes) => Some(bytes),
57            Artifact::Digest(_) => None,
58        }
59    }
60
61    /// Get the pre-computed digest if available
62    pub fn pre_computed_digest(&self) -> Option<Sha256Hash> {
63        match self {
64            Artifact::Bytes(_) => None,
65            Artifact::Digest(hash) => Some(*hash),
66        }
67    }
68}
69
70impl<'a> From<&'a [u8]> for Artifact<'a> {
71    fn from(bytes: &'a [u8]) -> Self {
72        Artifact::Bytes(bytes)
73    }
74}
75
76impl<'a> From<&'a Vec<u8>> for Artifact<'a> {
77    fn from(bytes: &'a Vec<u8>) -> Self {
78        Artifact::Bytes(bytes.as_slice())
79    }
80}
81
82impl<'a, const N: usize> From<&'a [u8; N]> for Artifact<'a> {
83    fn from(bytes: &'a [u8; N]) -> Self {
84        Artifact::Bytes(bytes.as_slice())
85    }
86}
87
88impl From<Sha256Hash> for Artifact<'static> {
89    fn from(hash: Sha256Hash) -> Self {
90        Artifact::Digest(hash)
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn test_artifact_from_bytes() {
100        let bytes = b"hello world";
101        let artifact = Artifact::from(bytes.as_slice());
102        assert!(artifact.has_bytes());
103        assert_eq!(artifact.bytes(), Some(bytes.as_slice()));
104    }
105
106    #[test]
107    fn test_artifact_from_digest() {
108        let digest = Sha256Hash::from_hex(
109            "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
110        )
111        .unwrap();
112        let artifact = Artifact::from(digest);
113        assert!(!artifact.has_bytes());
114        assert_eq!(artifact.bytes(), None);
115    }
116}