Skip to main content

release_kit/release/
embedded.rs

1//! The bundle compiled into this binary, behind the seam.
2//!
3//! The only source the front verbs read in the ordinary case: the
4//! embedded roots of `src/embedded.rs`, described by the same manifest
5//! `rk payload --json` prints. It answers both methods from memory, so a
6//! landing through the seam costs one digest pass over the payload and no
7//! I/O.
8
9use std::collections::HashMap;
10use std::sync::OnceLock;
11
12use crate::digest::Digest;
13use crate::embedded;
14use crate::error::RkError;
15
16use super::{Artifact, PAYLOAD_SCHEMA, ReleaseManifest, ReleaseSource, unknown_digest};
17
18/// The embedded release.
19#[derive(Debug, Default, Clone, Copy)]
20pub struct EmbeddedReleaseSource;
21
22/// The one manifest over the embedded bytes, computed once per process.
23fn manifest() -> &'static ReleaseManifest {
24    static MANIFEST: OnceLock<ReleaseManifest> = OnceLock::new();
25    MANIFEST.get_or_init(|| {
26        let artifacts = embedded::artifacts()
27            .into_iter()
28            .map(|(path, bytes)| Artifact {
29                path,
30                sha256: Digest::of(bytes),
31            })
32            .collect();
33        ReleaseManifest::new(
34            env!("CARGO_PKG_VERSION").to_owned(),
35            PAYLOAD_SCHEMA,
36            artifacts,
37        )
38    })
39}
40
41/// The embedded bytes by digest, computed once per process.
42fn blobs() -> &'static HashMap<Digest, &'static [u8]> {
43    static BLOBS: OnceLock<HashMap<Digest, &'static [u8]>> = OnceLock::new();
44    BLOBS.get_or_init(|| {
45        embedded::artifacts()
46            .into_iter()
47            .map(|(_, bytes)| (Digest::of(bytes), bytes))
48            .collect()
49    })
50}
51
52impl EmbeddedReleaseSource {
53    /// The manifest, borrowed for the process's lifetime.
54    #[must_use]
55    pub fn manifest_ref() -> &'static ReleaseManifest {
56        manifest()
57    }
58}
59
60impl ReleaseSource for EmbeddedReleaseSource {
61    fn manifest(&self) -> Result<ReleaseManifest, RkError> {
62        Ok(manifest().clone())
63    }
64
65    fn blob(&self, digest: &Digest) -> Result<Vec<u8>, RkError> {
66        blobs()
67            .get(digest)
68            .map(|bytes| bytes.to_vec())
69            .ok_or_else(|| unknown_digest(digest))
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::EmbeddedReleaseSource;
76    use crate::digest::Digest;
77    use crate::release::ReleaseSource;
78
79    #[test]
80    fn the_embedded_source_serves_every_artifact_it_names() {
81        let source = EmbeddedReleaseSource;
82        let manifest = source
83            .manifest()
84            .expect("the embedded bundle describes itself");
85        assert_eq!(manifest.release_kit_version, env!("CARGO_PKG_VERSION"));
86        assert_eq!(manifest.payload_schema, crate::release::PAYLOAD_SCHEMA);
87        assert!(!manifest.artifacts.is_empty());
88        for artifact in &manifest.artifacts {
89            let bytes = source.blob(&artifact.sha256).expect("a named blob reads");
90            assert_eq!(Digest::of(&bytes), artifact.sha256, "{}", artifact.path);
91        }
92        assert!(source.blob(&Digest::of(b"absent")).is_err());
93    }
94}