-
Notifications
You must be signed in to change notification settings - Fork 0
/
uint_list.go
105 lines (93 loc) · 2.03 KB
/
uint_list.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
// SPDX-License-Identifier: Apache-2.0
// Copyright © 2022 Wrangle Ltd
package objects
import (
"encoding/binary"
"fmt"
"io"
)
const maxUint32 = 1 << 32
// UintListEncoder encodes string slice. Max bytes size for each string is 65536 bytes
type UintListEncoder struct {
buf []byte
}
func NewUintListEncoder() *UintListEncoder {
return &UintListEncoder{
buf: make([]byte, 0, 256),
}
}
func (e *UintListEncoder) Encode(sl []uint32) []byte {
l := uint32(len(sl))
bufLen := 4 * int(l+1)
if bufLen > cap(e.buf) {
e.buf = make([]byte, bufLen)
} else {
e.buf = e.buf[:bufLen]
}
if len(sl) > maxUint32 {
panic(fmt.Errorf("slice length is too long (%d > 4294967296)", len(sl)))
}
binary.BigEndian.PutUint32(e.buf, l)
for i, u := range sl {
binary.BigEndian.PutUint32(e.buf[(i+1)*4:], u)
}
return e.buf
}
// UintListDecoder decodes string slice.
type UintListDecoder struct {
sl []uint32
buf []byte
pos int64
}
func NewUintListDecoder(reuseRecords bool) *UintListDecoder {
d := &UintListDecoder{
buf: make([]byte, 4),
}
if reuseRecords {
d.sl = make([]uint32, 0, 256)
}
return d
}
func (d *UintListDecoder) makeUintSlice(n uint32) []uint32 {
if d.sl == nil {
return make([]uint32, 0, n)
}
if n > uint32(cap(d.sl)) {
d.sl = make([]uint32, n)
}
return d.sl[:0]
}
func (d *UintListDecoder) Decode(b []byte) []uint32 {
n := binary.BigEndian.Uint32(b)
sl := d.makeUintSlice(n)
var i uint32
for i = 0; i < n; i++ {
sl = append(sl, binary.BigEndian.Uint32(b[(i+1)*4:]))
}
return sl
}
func (d *UintListDecoder) readUint32(r io.Reader) (uint32, error) {
n, err := r.Read(d.buf)
if err != nil {
return 0, err
}
d.pos += int64(n)
return binary.BigEndian.Uint32(d.buf), nil
}
func (d *UintListDecoder) Read(r io.Reader) (int64, []uint32, error) {
d.pos = 0
n, err := d.readUint32(r)
if err != nil {
return d.pos, nil, err
}
sl := d.makeUintSlice(n)
var i uint32
for i = 0; i < n; i++ {
u, err := d.readUint32(r)
if err != nil {
return d.pos, nil, err
}
sl = append(sl, u)
}
return d.pos, sl, nil
}