Skip to main content

arcbox_docker_tools/
lockfile.rs

1//! Parser for the `[[tools]]` section of `assets.lock`.
2
3use std::collections::HashMap;
4
5use serde::Deserialize;
6
7/// Top-level lockfile structure (only the parts we care about).
8#[derive(Debug, Deserialize)]
9pub struct AssetsLock {
10    #[serde(default)]
11    pub tools: Vec<ToolEntry>,
12}
13
14/// Per-architecture metadata for a tool.
15#[derive(Debug, Clone, Deserialize)]
16pub struct ArchEntry {
17    pub sha256: String,
18}
19
20/// A single `[[tools]]` entry.
21#[derive(Debug, Clone, Deserialize)]
22pub struct ToolEntry {
23    pub name: String,
24    pub version: String,
25    #[serde(default)]
26    pub arch: HashMap<String, ArchEntry>,
27}
28
29impl ToolEntry {
30    /// Returns the SHA-256 checksum for the given architecture, if present.
31    #[must_use]
32    pub fn sha256_for_arch(&self, arch: &str) -> Option<&str> {
33        // Accept common aliases.
34        let key = match arch {
35            "aarch64" => "arm64",
36            "amd64" => "x86_64",
37            _ => arch,
38        };
39        self.arch.get(key).map(|e| e.sha256.as_str())
40    }
41}
42
43/// Parse the `[[tools]]` entries from `assets.lock` TOML content.
44pub fn parse_tools(lock_toml: &str) -> Result<Vec<ToolEntry>, toml::de::Error> {
45    let lock: AssetsLock = toml::from_str(lock_toml)?;
46    Ok(lock.tools)
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    const SAMPLE: &str = r#"
54[boot]
55version = "0.5.1"
56cdn = "https://boot.arcboxcdn.com"
57
58[[tools]]
59name = "docker"
60version = "27.5.1"
61arch.arm64.sha256 = "aaa"
62arch.x86_64.sha256 = "bbb"
63
64[[tools]]
65name = "docker-buildx"
66version = "0.21.1"
67arch.arm64.sha256 = "ccc"
68"#;
69
70    #[test]
71    fn parse_tool_entries() {
72        let tools = parse_tools(SAMPLE).unwrap();
73        assert_eq!(tools.len(), 2);
74        assert_eq!(tools[0].name, "docker");
75        assert_eq!(tools[0].version, "27.5.1");
76        assert_eq!(tools[0].sha256_for_arch("arm64"), Some("aaa"));
77        assert_eq!(tools[0].sha256_for_arch("x86_64"), Some("bbb"));
78        assert_eq!(tools[1].sha256_for_arch("x86_64"), None);
79    }
80
81    #[test]
82    fn arch_aliases() {
83        let tools = parse_tools(SAMPLE).unwrap();
84        // "aarch64" should resolve to "arm64"
85        assert_eq!(tools[0].sha256_for_arch("aarch64"), Some("aaa"));
86        // "amd64" should resolve to "x86_64"
87        assert_eq!(tools[0].sha256_for_arch("amd64"), Some("bbb"));
88    }
89}