github.com/scottcagno/storage@v1.8.0/pkg/lsmt/binary/index.go (about) 1 package binary 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 ) 8 9 // Index is a binary entry index 10 type Index struct { 11 Key []byte 12 Offset int64 13 } 14 15 // String is the stringer method for a *Index 16 func (di *Index) String() string { 17 return fmt.Sprintf("index.key=%q, index.offset=%d", di.Key, di.Offset) 18 } 19 20 // EncodeIndex encodes and writes the provided entry index to w 21 func EncodeIndex(w io.WriteSeeker, e *Index) (int64, error) { 22 // error check 23 if e == nil { 24 return -1, ErrBadEntry 25 } 26 // get the file pointer offset for the entry 27 offset, err := w.Seek(0, io.SeekCurrent) 28 if err != nil { 29 return -1, err 30 } 31 // make buffer 32 buf := make([]byte, 18) 33 // encode and write entry key length 34 binary.LittleEndian.PutUint64(buf[0:8], uint64(len(e.Key))) 35 _, err = w.Write(buf[0:8]) 36 if err != nil { 37 return -1, err 38 } 39 // encode and write entry index data offset 40 binary.PutVarint(buf[8:18], e.Offset) 41 _, err = w.Write(buf[8:18]) 42 if err != nil { 43 return -1, err 44 } 45 // write entry key 46 _, err = w.Write(e.Key) 47 if err != nil { 48 return -1, err 49 } 50 return offset, nil 51 } 52 53 // DecodeIndex reads and decodes the provided entry index from r 54 func DecodeIndex(r io.Reader) (*Index, error) { 55 // make buffer 56 buf := make([]byte, 18) 57 // read entry key length 58 _, err := r.Read(buf[0:8]) 59 if err != nil { 60 return nil, err 61 } 62 // read entry data offset 63 _, err = r.Read(buf[8:18]) 64 if err != nil { 65 return nil, err 66 } 67 // decode key length 68 klen := binary.LittleEndian.Uint64(buf[0:8]) 69 // decode data offset 70 off, _ := binary.Varint(buf[8:18]) 71 // make entry index 72 e := &Index{ 73 Key: make([]byte, klen), 74 Offset: off, 75 } 76 // read key from data into entry key 77 _, err = r.Read(e.Key) 78 if err != nil { 79 return nil, err 80 } 81 // return entry 82 return e, nil 83 } 84 85 // DecodeIndexAt decodes the index at the provided offset using the provided reader 86 func DecodeIndexAt(r io.ReaderAt, offset int64) (*Index, error) { 87 // make buffer 88 buf := make([]byte, 18) 89 // read entry key length 90 n, err := r.ReadAt(buf[0:8], offset) 91 if err != nil { 92 return nil, err 93 } 94 // update offset 95 offset += int64(n) 96 // read entry data offset 97 n, err = r.ReadAt(buf[8:18], offset) 98 if err != nil { 99 return nil, err 100 } 101 // update offset 102 offset += int64(n) 103 // decode key length 104 klen := binary.LittleEndian.Uint64(buf[0:8]) 105 // decode data offset 106 off, _ := binary.Varint(buf[8:18]) 107 // make entry index 108 e := &Index{ 109 Key: make([]byte, klen), 110 Offset: off, 111 } 112 // read key from data into entry key 113 n, err = r.ReadAt(e.Key, offset) 114 if err != nil { 115 return nil, err 116 } 117 // update offset 118 offset += int64(n) 119 // return entry 120 return e, nil 121 }