github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/ident/ident.go (about) 1 package ident 2 3 import ( 4 "crypto/sha256" 5 "encoding/binary" 6 "encoding/hex" 7 "hash" 8 "sort" 9 ) 10 11 type Identifiable interface { 12 Identity() []byte 13 } 14 15 type AddressProvider interface { 16 ContentAddress(entity Identifiable) string 17 } 18 19 type HexAddressProvider struct{} 20 21 func NewHexAddressProvider() *HexAddressProvider { 22 return &HexAddressProvider{} 23 } 24 25 func (*HexAddressProvider) ContentAddress(entity Identifiable) string { 26 return hex.EncodeToString(entity.Identity()) 27 } 28 29 type AddressType uint8 30 31 const ( 32 AddressTypeBytes AddressType = iota 33 AddressTypeString 34 AddressTypeInt64 35 AddressTypeStringSlice 36 AddressTypeStringMap 37 AddressTypeEmbeddedIdentifiable 38 ) 39 40 // linter is angry because h can be an io.Writer, but we explicitly want a Hash here. 41 // 42 //nolint:interfacer 43 func marshalType(h hash.Hash, addressType AddressType) { 44 _, _ = h.Write([]byte{byte(addressType)}) 45 } 46 47 func MarshalBytes(h hash.Hash, v []byte) { 48 marshalType(h, AddressTypeBytes) 49 MarshalInt64(h, int64(len(v))) 50 _, _ = h.Write(v) 51 } 52 53 func MarshalString(h hash.Hash, v string) { 54 marshalType(h, AddressTypeString) 55 MarshalInt64(h, int64(len(v))) 56 _, _ = h.Write([]byte(v)) 57 } 58 59 func MarshalInt64(h hash.Hash, v int64) { 60 const int64Bytes = 8 61 marshalType(h, AddressTypeInt64) 62 _, _ = h.Write([]byte{int64Bytes}) 63 bytes := make([]byte, int64Bytes) 64 binary.BigEndian.PutUint64(bytes, uint64(v)) 65 _, _ = h.Write(bytes) 66 } 67 68 func MarshalStringSlice(h hash.Hash, v []string) { 69 marshalType(h, AddressTypeStringSlice) 70 MarshalInt64(h, int64(len(v))) 71 for _, item := range v { 72 MarshalString(h, item) 73 } 74 } 75 76 func MarshalStringMap(h hash.Hash, v map[string]string) { 77 marshalType(h, AddressTypeStringMap) 78 MarshalInt64(h, int64(len(v))) 79 keys := make([]string, len(v)) 80 i := 0 81 for k := range v { 82 keys[i] = k 83 i++ 84 } 85 sort.Strings(keys) 86 for _, k := range keys { 87 MarshalString(h, k) 88 MarshalString(h, v[k]) 89 } 90 } 91 92 func MarshalIdentifiable(h hash.Hash, v Identifiable) { 93 marshalType(h, AddressTypeEmbeddedIdentifiable) 94 MarshalBytes(h, v.Identity()) 95 } 96 97 type AddressWriter struct { 98 hash.Hash 99 } 100 101 func NewAddressWriter() *AddressWriter { 102 return &AddressWriter{Hash: sha256.New()} 103 } 104 105 func (b *AddressWriter) MarshalBytes(v []byte) *AddressWriter { 106 MarshalBytes(b, v) 107 return b 108 } 109 110 func (b *AddressWriter) MarshalString(v string) *AddressWriter { 111 MarshalString(b, v) 112 return b 113 } 114 115 func (b *AddressWriter) MarshalStringOpt(v string) *AddressWriter { 116 if len(v) > 0 { 117 MarshalString(b, v) 118 } 119 return b 120 } 121 122 func (b *AddressWriter) MarshalInt64(v int64) *AddressWriter { 123 MarshalInt64(b, v) 124 return b 125 } 126 127 func (b *AddressWriter) MarshalStringSlice(v []string) *AddressWriter { 128 MarshalStringSlice(b, v) 129 return b 130 } 131 132 func (b *AddressWriter) MarshalStringMap(v map[string]string) *AddressWriter { 133 MarshalStringMap(b, v) 134 return b 135 } 136 137 func (b *AddressWriter) MarshalIdentifiable(v Identifiable) *AddressWriter { 138 MarshalIdentifiable(b, v) 139 return b 140 } 141 142 func (b *AddressWriter) Identity() []byte { 143 return b.Sum(nil) 144 }