LCOV - code coverage report
Current view: top level - pebble/sstable/colblk - unsafe_slice.go (source / functions) Hit Total Coverage
Test: 2024-07-11 08:15Z e727ab74 - tests only.lcov Lines: 12 45 26.7 %
Date: 2024-07-11 08:16:24 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2024 The LevelDB-Go and Pebble Authors. All rights reserved. Use
       2             : // of this source code is governed by a BSD-style license that can be found in
       3             : // the LICENSE file.
       4             : 
       5             : package colblk
       6             : 
       7             : import (
       8             :         "unsafe"
       9             : 
      10             :         "github.com/cockroachdb/errors"
      11             :         "golang.org/x/exp/constraints"
      12             : )
      13             : 
      14             : // UnsafeRawSlice maintains a pointer to a slice of elements of type T.
      15             : // UnsafeRawSlice provides no bounds checking.
      16             : type UnsafeRawSlice[T constraints.Integer] struct {
      17             :         ptr unsafe.Pointer
      18             : }
      19             : 
      20           1 : func makeUnsafeRawSlice[T constraints.Integer](ptr unsafe.Pointer) UnsafeRawSlice[T] {
      21           1 :         if align(uintptr(ptr), unsafe.Sizeof(T(0))) != uintptr(ptr) {
      22           0 :                 panic(errors.AssertionFailedf("slice pointer %p not %d-byte aligned", ptr, unsafe.Sizeof(T(0))))
      23             :         }
      24           1 :         return UnsafeRawSlice[T]{ptr: ptr}
      25             : }
      26             : 
      27             : // At returns the `i`-th element of the slice.
      28           1 : func (s UnsafeRawSlice[T]) At(i int) T {
      29           1 :         return *(*T)(unsafe.Pointer(uintptr(s.ptr) + unsafe.Sizeof(T(0))*uintptr(i)))
      30           1 : }
      31             : 
      32             : // Slice returns a go []T slice containing the first `len` elements of the
      33             : // unsafe slice.
      34           1 : func (s UnsafeRawSlice[T]) Slice(len int) []T {
      35           1 :         return unsafe.Slice((*T)(s.ptr), len)
      36           1 : }
      37             : 
      38             : // set mutates the slice, setting the `i`-th value to `v`.
      39           1 : func (s UnsafeRawSlice[T]) set(i int, v T) {
      40           1 :         *(*T)(unsafe.Pointer(uintptr(s.ptr) + unsafe.Sizeof(T(0))*uintptr(i))) = v
      41           1 : }
      42             : 
      43             : // UnsafeUint8s is an UnsafeIntegerSlice of uint8s, possibly using delta
      44             : // encoding internally.
      45             : type UnsafeUint8s = UnsafeIntegerSlice[uint8]
      46             : 
      47             : // UnsafeUint16s is an UnsafeIntegerSlice of uint16s, possibly using delta
      48             : // encoding internally.
      49             : type UnsafeUint16s = UnsafeIntegerSlice[uint16]
      50             : 
      51             : // UnsafeUint32s is an UnsafeIntegerSlice of uint32s, possibly using delta
      52             : // encoding internally.
      53             : type UnsafeUint32s = UnsafeIntegerSlice[uint32]
      54             : 
      55             : // UnsafeUint64s is an UnsafeIntegerSlice of uint64s, possibly using delta
      56             : // encoding internally.
      57             : type UnsafeUint64s = UnsafeIntegerSlice[uint64]
      58             : 
      59             : // UnsafeIntegerSlice exposes a read-only slice of integers from a column. If
      60             : // the column's values are delta-encoded, UnsafeIntegerSlice transparently
      61             : // applies deltas.
      62             : //
      63             : // See DeltaEncoding and UintBuilder.
      64             : type UnsafeIntegerSlice[T constraints.Integer] struct {
      65             :         base       T
      66             :         deltaPtr   unsafe.Pointer
      67             :         deltaWidth uintptr
      68             : }
      69             : 
      70             : func makeUnsafeIntegerSlice[T constraints.Integer](
      71             :         base T, deltaPtr unsafe.Pointer, deltaWidth int,
      72           0 : ) UnsafeIntegerSlice[T] {
      73           0 :         return UnsafeIntegerSlice[T]{
      74           0 :                 base:       base,
      75           0 :                 deltaPtr:   deltaPtr,
      76           0 :                 deltaWidth: uintptr(deltaWidth),
      77           0 :         }
      78           0 : }
      79             : 
      80             : // TODO(jackson): Remove when more of the read path is hooked up.
      81             : var _ = makeUnsafeIntegerSlice[uint64]
      82             : 
      83             : // At returns the `i`-th element of the slice.
      84           0 : func (s UnsafeIntegerSlice[T]) At(i int) T {
      85           0 :         // TODO(jackson): Experiment with other alternatives that might be faster
      86           0 :         // and avoid switching on the width.
      87           0 :         switch s.deltaWidth {
      88           0 :         case 0:
      89           0 :                 return s.base
      90           0 :         case 1:
      91           0 :                 return s.base + T(*(*uint8)(unsafe.Pointer(uintptr(s.deltaPtr) + uintptr(i))))
      92           0 :         case 2:
      93           0 :                 return s.base + T(*(*uint16)(unsafe.Pointer(uintptr(s.deltaPtr) + uintptr(i)<<align16Shift)))
      94           0 :         case 4:
      95           0 :                 return s.base + T(*(*uint32)(unsafe.Pointer(uintptr(s.deltaPtr) + uintptr(i)<<align32Shift)))
      96           0 :         case 8:
      97           0 :                 // NB: The slice encodes 64-bit integers, there is no base (it doesn't
      98           0 :                 // save any bits to compute a delta) and T must be a 64-bit integer. We
      99           0 :                 // cast directly into a *T pointer and don't add the base.
     100           0 :                 return (*(*T)(unsafe.Pointer(uintptr(s.deltaPtr) + uintptr(i)<<align64Shift)))
     101           0 :         default:
     102           0 :                 panic("unreachable")
     103             :         }
     104             : }
     105             : 
     106             : // Clone allocates a new slice and copies the first `rows` elements.
     107           0 : func (s UnsafeIntegerSlice[T]) Clone(rows int) []T {
     108           0 :         result := make([]T, rows)
     109           0 :         for i := 0; i < rows; i++ {
     110           0 :                 result[i] = s.At(i)
     111           0 :         }
     112           0 :         return result
     113             : }

Generated by: LCOV version 1.14