1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_oci_annotation::Annotation;
5use use_oci_descriptor::OciDescriptor;
6use use_oci_platform::OciPlatform;
7
8#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct IndexManifest {
11 descriptor: OciDescriptor,
12 platform: Option<OciPlatform>,
13 annotations: Vec<Annotation>,
14}
15
16impl IndexManifest {
17 #[must_use]
19 pub fn new(descriptor: OciDescriptor) -> Self {
20 Self {
21 descriptor,
22 platform: None,
23 annotations: Vec::new(),
24 }
25 }
26
27 #[must_use]
29 pub fn with_platform(mut self, platform: OciPlatform) -> Self {
30 self.platform = Some(platform);
31 self
32 }
33
34 #[must_use]
36 pub fn with_annotation(mut self, annotation: Annotation) -> Self {
37 self.annotations.push(annotation);
38 self
39 }
40
41 #[must_use]
43 pub const fn descriptor(&self) -> &OciDescriptor {
44 &self.descriptor
45 }
46
47 #[must_use]
49 pub const fn platform(&self) -> Option<&OciPlatform> {
50 self.platform.as_ref()
51 }
52
53 #[must_use]
55 pub fn annotations(&self) -> &[Annotation] {
56 &self.annotations
57 }
58}
59
60#[derive(Clone, Debug, Default, Eq, PartialEq)]
62pub struct OciIndex {
63 manifests: Vec<IndexManifest>,
64 annotations: Vec<Annotation>,
65}
66
67impl OciIndex {
68 #[must_use]
70 pub const fn new() -> Self {
71 Self {
72 manifests: Vec::new(),
73 annotations: Vec::new(),
74 }
75 }
76
77 #[must_use]
79 pub fn with_manifest(mut self, manifest: IndexManifest) -> Self {
80 self.manifests.push(manifest);
81 self
82 }
83
84 #[must_use]
86 pub fn with_annotation(mut self, annotation: Annotation) -> Self {
87 self.annotations.push(annotation);
88 self
89 }
90
91 #[must_use]
93 pub fn manifests(&self) -> &[IndexManifest] {
94 &self.manifests
95 }
96
97 #[must_use]
99 pub fn annotations(&self) -> &[Annotation] {
100 &self.annotations
101 }
102}
103
104#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
106pub struct IndexMetadata {
107 manifest_count: usize,
108}
109
110impl IndexMetadata {
111 #[must_use]
113 pub const fn new(manifest_count: usize) -> Self {
114 Self { manifest_count }
115 }
116
117 #[must_use]
119 pub const fn manifest_count(self) -> usize {
120 self.manifest_count
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::{IndexManifest, IndexMetadata, OciIndex};
127 use use_oci_descriptor::{DescriptorSize, OciDescriptor};
128 use use_oci_digest::OciDigest;
129 use use_oci_media_type::OciMediaType;
130 use use_oci_platform::{OciArchitecture, OciOs, OciPlatform};
131
132 const SHA: &str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
133
134 #[test]
135 fn models_index_entries() -> Result<(), Box<dyn std::error::Error>> {
136 let digest: OciDigest = format!("sha256:{SHA}").parse()?;
137 let descriptor = OciDescriptor::new(
138 OciMediaType::image_manifest(),
139 digest,
140 DescriptorSize::new(10),
141 );
142 let platform = OciPlatform::new(OciOs::Linux, OciArchitecture::Arm64);
143 let entry = IndexManifest::new(descriptor).with_platform(platform.clone());
144 let index = OciIndex::new().with_manifest(entry);
145
146 assert_eq!(index.manifests().len(), 1);
147 assert_eq!(index.manifests()[0].platform(), Some(&platform));
148 assert_eq!(
149 IndexMetadata::new(index.manifests().len()).manifest_count(),
150 1
151 );
152 Ok(())
153 }
154}