use super::git_sha::GitSha;
use super::schema_version::SchemaVersion;
use super::sha256_digest::Sha256Digest;
use super::target::TargetTriple;
use super::toolchain_channel::ToolchainChannel;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ManifestProvenance {
pub git_sha: GitSha,
pub schema_version: SchemaVersion,
pub toolchain: ToolchainChannel,
pub target: TargetTriple,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ManifestContent {
pub generated_at: GeneratedAt,
pub files: Vec<String>,
pub sha256: Sha256Digest,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Manifest {
#[serde(flatten)]
provenance: ManifestProvenance,
#[serde(flatten)]
content: ManifestContent,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct GeneratedAt(String);
impl GeneratedAt {
#[must_use]
pub fn new(value: impl Into<String>) -> Self {
Self(value.into())
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for GeneratedAt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! _manifest_doc_setup {
($manifest:ident) => {
use whitaker_installer::artefact::git_sha::GitSha;
use whitaker_installer::artefact::manifest::{
GeneratedAt, Manifest, ManifestContent, ManifestProvenance,
};
use whitaker_installer::artefact::schema_version::SchemaVersion;
use whitaker_installer::artefact::sha256_digest::Sha256Digest;
use whitaker_installer::artefact::target::TargetTriple;
use whitaker_installer::artefact::toolchain_channel::ToolchainChannel;
let provenance = ManifestProvenance {
git_sha: GitSha::try_from("abc1234").expect("valid git SHA"),
schema_version: SchemaVersion::current(),
toolchain: ToolchainChannel::try_from("nightly-2025-09-18")
.expect("valid toolchain channel"),
target: TargetTriple::try_from("x86_64-unknown-linux-gnu")
.expect("valid target triple"),
};
let content = ManifestContent {
generated_at: GeneratedAt::new("2026-02-03T00:00:00Z"),
files: vec!["libwhitaker_lints.so".to_owned()],
sha256: Sha256Digest::try_from("a".repeat(64).as_str()).expect("valid SHA-256 digest"),
};
let $manifest = Manifest::new(provenance, content);
};
}
impl Manifest {
#[must_use]
pub fn new(provenance: ManifestProvenance, content: ManifestContent) -> Self {
Self {
provenance,
content,
}
}
#[must_use]
pub fn git_sha(&self) -> &GitSha {
&self.provenance.git_sha
}
#[must_use]
pub fn schema_version(&self) -> SchemaVersion {
self.provenance.schema_version
}
#[must_use]
pub fn toolchain(&self) -> &ToolchainChannel {
&self.provenance.toolchain
}
#[must_use]
pub fn target(&self) -> &TargetTriple {
&self.provenance.target
}
#[must_use]
pub fn generated_at(&self) -> &GeneratedAt {
&self.content.generated_at
}
#[must_use]
pub fn files(&self) -> &[String] {
&self.content.files
}
#[must_use]
pub fn sha256(&self) -> &Sha256Digest {
&self.content.sha256
}
}
#[cfg(test)]
#[path = "manifest_tests.rs"]
mod tests;