File size: 2,238 Bytes
e36aeda | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | go build main.go
! stdout .
! stderr .
-- main.go --
package main
import (
"p/b"
)
func main() {
f()
}
func f() {
typ := indexedPageType{newIndexedType(nil)}
page := newPage(typ.indexedType)
page.Data()
}
func newPage(typ *indexedType) Page {
values := typ.NewValues(nil, nil)
return &indexedPage{
typ: typ,
values: values.Int32(),
columnIndex: ^0,
}
}
type Type interface {
NewPage(columnIndex, numValues int, data b.Values) Page
NewValues(values []byte, offsets []uint32) b.Values
}
type Page interface {
Type() Type
Data() b.Values
}
type indexedPage struct {
typ *indexedType
values []int32
columnIndex int16
}
func (page *indexedPage) Type() Type { return indexedPageType{page.typ} }
func (page *indexedPage) Data() b.Values { return b.Int32Values(page.values) }
type indexedType struct {
Type
}
func newIndexedType(typ Type) *indexedType {
return &indexedType{Type: typ}
}
type indexedPageType struct{ *indexedType }
func (t indexedPageType) NewValues(values []byte, _ []uint32) b.Values {
return b.Int32ValuesFromBytes(values)
}
-- go.mod --
module p
go 1.24
-- internal/a/a.go --
package a
import "unsafe"
type slice struct {
ptr unsafe.Pointer
len int
cap int
}
func Slice[To, From any](data []From) []To {
// This function could use unsafe.Slice but it would drop the capacity
// information, so instead we implement the type conversion.
var zf From
var zt To
var s = slice{
ptr: unsafe.Pointer(unsafe.SliceData(data)),
len: int((uintptr(len(data)) * unsafe.Sizeof(zf)) / unsafe.Sizeof(zt)),
cap: int((uintptr(cap(data)) * unsafe.Sizeof(zf)) / unsafe.Sizeof(zt)),
}
return *(*[]To)(unsafe.Pointer(&s))
}
-- b/b.go --
package b
import "p/internal/a"
type Kind int32
const Int32 Kind = iota + 2
type Values struct {
kind Kind
size int32
data []byte
offsets []uint32
}
func (v *Values) Int32() []int32 {
return a.Slice[int32](v.data)
}
func makeValues[T any](kind Kind, values []T) Values {
return Values{kind: kind, data: a.Slice[byte](values)}
}
func Int32Values(values []int32) Values {
return makeValues(Int32, values)
}
func Int32ValuesFromBytes(values []byte) Values {
return Values{kind: Int32, data: values}
}
|