...
1 package ocimem
2
3 import (
4 "encoding/json"
5 "errors"
6 "fmt"
7
8 "cuelabs.dev/go/oci/ociregistry"
9 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
10 )
11
12 type refKind int
13
14 const (
15 kindSubjectManifest refKind = iota
16 kindBlob
17 kindManifest
18 )
19
20 type descInfo struct {
21 name string
22 kind refKind
23 desc ociregistry.Descriptor
24 }
25
26 type descIter func(yield func(descInfo) bool)
27
28
29 var manifestIterators = map[string]func(data []byte) (descIter, error){
30 ocispec.MediaTypeImageManifest: descIterForType(imageDescIter),
31 ocispec.MediaTypeImageIndex: descIterForType(indexDescIter),
32 }
33
34 var errUnknownManifestMediaTypeForIteration = errors.New("cannot determine references in unknown media type")
35
36
37
38
39 func manifestReferences(mediaType string, data []byte) (descIter, error) {
40 dataIter := manifestIterators[mediaType]
41 if dataIter == nil {
42
43
44 return func(func(descInfo) bool) {}, nil
45 }
46 return dataIter(data)
47 }
48
49
50
51 func repoTagIter(r *repository) descIter {
52 return func(yield func(descInfo) bool) {
53 for tag, desc := range r.tags {
54 if !yield(descInfo{
55 name: tag,
56 desc: desc,
57 kind: kindManifest,
58 }) {
59 break
60 }
61 }
62 }
63 }
64
65 func descIterForType[T any](newIter func(T) descIter) func(data []byte) (descIter, error) {
66 return func(data []byte) (descIter, error) {
67 var x T
68 if err := json.Unmarshal(data, &x); err != nil {
69 return nil, fmt.Errorf("cannot unmarshal into %T: %v", &x, err)
70 }
71 return newIter(x), nil
72 }
73 }
74
75 func imageDescIter(m ociregistry.Manifest) descIter {
76 return func(yield func(descInfo) bool) {
77 for i, layer := range m.Layers {
78 if !yield(descInfo{
79 name: fmt.Sprintf("layers[%d]", i),
80 desc: layer,
81 kind: kindBlob,
82 }) {
83 return
84 }
85 }
86 if !yield(descInfo{
87 name: "config",
88 desc: m.Config,
89 kind: kindBlob,
90 }) {
91 return
92 }
93 if m.Subject != nil {
94 if !yield(descInfo{
95 name: "subject",
96 kind: kindSubjectManifest,
97 desc: *m.Subject,
98 }) {
99 return
100 }
101 }
102 }
103 }
104
105 func indexDescIter(m ocispec.Index) descIter {
106 return func(yield func(descInfo) bool) {
107 for i, manifest := range m.Manifests {
108 if !yield(descInfo{
109 name: fmt.Sprintf("manifests[%d]", i),
110 kind: kindManifest,
111 desc: manifest,
112 }) {
113 return
114 }
115 }
116 if m.Subject != nil {
117 if !yield(descInfo{
118 name: "subject",
119 kind: kindSubjectManifest,
120 desc: *m.Subject,
121 }) {
122 return
123 }
124 }
125 }
126 }
127
View as plain text