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  }