forked from segmentio/parquet-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
null.go
124 lines (99 loc) · 2.47 KB
/
null.go
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
//go:build go1.18
package parquet
import (
"reflect"
"unsafe"
"github.com/segmentio/parquet-go/deprecated"
"github.com/segmentio/parquet-go/internal/bytealg"
"github.com/segmentio/parquet-go/internal/unsafecast"
"github.com/segmentio/parquet-go/sparse"
)
// nullIndexFunc is the type of functions used to detect null values in rows.
//
// For each value of the rows array, the bitmap passed as first argument is
// populated to indicate whether the values were null (0) or not (1).
//
// The function writes one bit to the output buffer for each row in the input,
// the buffer must be sized accordingly.
type nullIndexFunc func(bits []uint64, rows sparse.Array)
func nullIndex[T comparable](bits []uint64, rows sparse.Array) {
var zero T
for i := 0; i < rows.Len(); i++ {
v := *(*T)(rows.Index(i))
if v != zero {
x := uint(i) / 64
y := uint(i) % 64
bits[x] |= 1 << y
}
}
}
func nullIndexStruct(bits []uint64, rows sparse.Array) {
bytealg.Broadcast(unsafecast.Slice[byte](bits), 0xFF)
}
func nullIndexFuncOf(t reflect.Type) nullIndexFunc {
switch t {
case reflect.TypeOf(deprecated.Int96{}):
return nullIndex[deprecated.Int96]
}
switch t.Kind() {
case reflect.Bool:
return nullIndexBool
case reflect.Int:
return nullIndexInt
case reflect.Int32:
return nullIndexInt32
case reflect.Int64:
return nullIndexInt64
case reflect.Uint:
return nullIndexUint
case reflect.Uint32:
return nullIndexUint32
case reflect.Uint64:
return nullIndexUint64
case reflect.Float32:
return nullIndexFloat32
case reflect.Float64:
return nullIndexFloat64
case reflect.String:
return nullIndexString
case reflect.Slice:
return nullIndexSlice
case reflect.Map:
return nullIndexPointer
case reflect.Array:
if t.Elem().Kind() == reflect.Uint8 {
switch size := t.Len(); size {
case 16:
return nullIndexUint128
default:
return nullIndexFuncOfByteArray(size)
}
}
case reflect.Pointer:
return nullIndexPointer
case reflect.Struct:
return nullIndexStruct
}
panic("cannot convert Go values of type " + typeNameOf(t) + " to parquet value")
}
func nullIndexFuncOfByteArray(n int) nullIndexFunc {
return func(bits []uint64, rows sparse.Array) {
for i := 0; i < rows.Len(); i++ {
p := (*byte)(rows.Index(i))
b := unsafe.Slice(p, n)
if !isZero(b) {
x := uint(i) / 64
y := uint(i) % 64
bits[x] |= 1 << y
}
}
}
}
func isZero(b []byte) bool {
for _, c := range b {
if c != 0 {
return false
}
}
return true
}