github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/prolly/message/serialize.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package message 16 17 import ( 18 "math" 19 20 fb "github.com/dolthub/flatbuffers/v23/go" 21 22 "github.com/dolthub/dolt/go/store/hash" 23 "github.com/dolthub/dolt/go/store/pool" 24 "github.com/dolthub/dolt/go/store/val" 25 ) 26 27 const ( 28 MaxVectorOffset = uint64(math.MaxUint16) 29 ) 30 31 func getFlatbufferBuilder(pool pool.BuffPool, sz int) (b *fb.Builder) { 32 b = fb.NewBuilder(0) 33 b.Bytes = pool.Get(uint64(sz)) 34 b.Reset() 35 return 36 } 37 38 func writeItemBytes(b *fb.Builder, items [][]byte, sumSz int) fb.UOffsetT { 39 b.Prep(fb.SizeUOffsetT, sumSz) 40 41 stop := int(b.Head()) 42 start := stop - sumSz 43 for _, item := range items { 44 copy(b.Bytes[start:stop], item) 45 start += len(item) 46 } 47 48 start = stop - sumSz 49 return b.CreateByteVector(b.Bytes[start:stop]) 50 } 51 52 // writeItemOffsets writes (n+1) uint16 offStart for n |items|. 53 // the first offset is 0, the last offset is |sumSz|. 54 func writeItemOffsets(b *fb.Builder, items [][]byte, sumSz int) fb.UOffsetT { 55 var off = sumSz 56 for i := len(items) - 1; i >= 0; i-- { 57 b.PrependUint16(uint16(off)) 58 off -= len(items[i]) 59 } 60 assertTrue(off == 0, "incorrect final value after serializing offStart") 61 b.PrependUint16(uint16(off)) 62 return b.EndVector(len(items) + 1) 63 } 64 65 // countAddresses returns the number of chunk addresses stored within |items|. 66 func countAddresses(items [][]byte, td val.TupleDesc) (cnt int) { 67 for i := len(items) - 1; i >= 0; i-- { 68 val.IterAddressFields(td, func(j int, t val.Type) { 69 // get offset of address withing |tup| 70 addr := val.Tuple(items[i]).GetField(j) 71 if len(addr) > 0 && !hash.New(addr).IsEmpty() { 72 cnt++ 73 } 74 return 75 }) 76 } 77 return 78 } 79 80 // writeAddressOffsets serializes an array of uint16 offStart representing address offStart within an array of items. 81 func writeAddressOffsets(b *fb.Builder, items [][]byte, sumSz int, td val.TupleDesc) fb.UOffsetT { 82 var cnt int 83 var off = sumSz 84 for i := len(items) - 1; i >= 0; i-- { 85 tup := val.Tuple(items[i]) 86 off -= len(tup) // start of tuple 87 val.IterAddressFields(td, func(j int, t val.Type) { 88 addr := val.Tuple(items[i]).GetField(j) 89 if len(addr) == 0 || hash.New(addr).IsEmpty() { 90 return 91 } 92 // get offset of address withing |tup| 93 o, _ := tup.GetOffset(j) 94 o += off // offset is tuple start plus field start 95 b.PrependUint16(uint16(o)) 96 cnt++ 97 }) 98 } 99 return b.EndVector(cnt) 100 } 101 102 func writeCountArray(b *fb.Builder, counts []uint64) fb.UOffsetT { 103 buf := make([]byte, maxEncodedSize(len(counts))) 104 return b.CreateByteVector(encodeVarints(counts, buf)) 105 } 106 107 func sumSubtrees(subtrees []uint64) (sum uint64) { 108 for i := range subtrees { 109 sum += subtrees[i] 110 } 111 return 112 }