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}
}