...
1
16
17 package continuity
18
19 import (
20 "fmt"
21 "io"
22 "sort"
23
24 "github.com/opencontainers/go-digest"
25 )
26
27
28 type Digester interface {
29 Digest(io.Reader) (digest.Digest, error)
30 }
31
32
33 type ContentProvider interface {
34 Reader(digest.Digest) (io.ReadCloser, error)
35 }
36
37 type simpleDigester struct {
38 algorithm digest.Algorithm
39 }
40
41 func (sd simpleDigester) Digest(r io.Reader) (digest.Digest, error) {
42 digester := sd.algorithm.Digester()
43
44 if _, err := io.Copy(digester.Hash(), r); err != nil {
45 return "", err
46 }
47
48 return digester.Digest(), nil
49 }
50
51
52
53
54
55 func uniqifyDigests(digests ...digest.Digest) ([]digest.Digest, error) {
56 sort.Stable(digestSlice(digests))
57 seen := map[digest.Digest]struct{}{}
58 algs := map[digest.Algorithm][]digest.Digest{}
59
60 var out []digest.Digest
61
62 for _, d := range digests {
63 if _, ok := seen[d]; ok {
64 continue
65 }
66
67 seen[d] = struct{}{}
68 algs[d.Algorithm()] = append(algs[d.Algorithm()], d)
69
70 if len(algs[d.Algorithm()]) > 1 {
71 return nil, fmt.Errorf("conflicting digests for %v found", d.Algorithm())
72 }
73
74 out = append(out, d)
75 }
76
77 return out, nil
78 }
79
80
81 func digestsMatch(as, bs []digest.Digest) bool {
82 all := append(as, bs...)
83
84 uniqified, err := uniqifyDigests(all...)
85 if err != nil {
86
87 return false
88 }
89
90 disjoint := len(as) + len(bs)
91
92
93 return len(uniqified) != disjoint
94 }
95
96 type digestSlice []digest.Digest
97
98 func (p digestSlice) Len() int { return len(p) }
99 func (p digestSlice) Less(i, j int) bool { return p[i] < p[j] }
100 func (p digestSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
101
View as plain text