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