containerd_store/
types.rs1use std::fmt;
2use std::path::PathBuf;
3
4use serde::{Deserialize, Serialize};
5use thiserror::Error;
6
7#[derive(Debug, Error)]
8pub enum StoreError {
9 #[error("BoltDB open error: {0}")]
10 DbOpen(String),
11 #[error("BoltDB access error: {0}")]
12 Db(String),
13 #[error("Containerd images bucket not found (namespace: {0})")]
14 ImagesBucketMissing(String),
15 #[error("Image not found: {0}")]
16 ImageNotFound(String),
17 #[error("Descriptor missing for image: {0}")]
18 DescriptorMissing(String),
19 #[error("Invalid UTF-8 in key/value: {0}")]
20 Utf8(String),
21 #[error("Invalid digest format: {0}")]
22 Digest(String),
23 #[error("IO error: {0}")]
24 Io(#[from] std::io::Error),
25 #[error("JSON parse error: {0}")]
26 Json(#[from] serde_json::Error),
27}
28
29pub type Result<T> = std::result::Result<T, StoreError>;
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct Descriptor {
33 pub media_type: String,
34 pub digest: String,
35 pub size: i64,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct ImageEntry {
40 pub name: String,
41 pub target: Descriptor,
42 pub created_at: Option<String>,
43 pub updated_at: Option<String>,
44}
45
46#[derive(Debug, Clone)]
47pub struct ResolvedImage {
48 pub entry: ImageEntry,
49 pub manifest_path: PathBuf,
50}
51
52#[derive(Debug, Clone)]
53pub struct ManifestInfo {
54 pub config_digest: Option<String>,
55 pub layer_digests: Vec<String>,
56 pub raw: Vec<u8>,
57}
58
59#[derive(Debug, Clone)]
60pub struct PortableImageExport {
61 pub manifest_digest: String,
62 pub blobs_root: PathBuf,
63 pub copied: Vec<String>,
64}
65
66#[derive(Debug, Clone)]
67pub struct DigestRef {
68 pub algo: String,
69 pub hex: String,
70}
71
72impl fmt::Display for DigestRef {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(f, "{}:{}", self.algo, self.hex)
75 }
76}
77
78impl DigestRef {
79 pub fn parse(d: &str) -> Result<Self> {
80 let mut parts = d.splitn(2, ':');
81 let algo = parts
82 .next()
83 .ok_or_else(|| StoreError::Digest("missing algo".into()))?;
84 let hex = parts
85 .next()
86 .ok_or_else(|| StoreError::Digest("missing hex".into()))?;
87 if algo.is_empty() || hex.is_empty() {
88 return Err(StoreError::Digest("empty digest parts".into()));
89 }
90 Ok(DigestRef {
91 algo: algo.to_string(),
92 hex: hex.to_string(),
93 })
94 }
95
96 pub fn path_under(&self, root: &PathBuf) -> PathBuf {
97 root.join(&self.algo).join(&self.hex)
98 }
99}