-
Notifications
You must be signed in to change notification settings - Fork 0
/
arena.go
64 lines (52 loc) · 1.68 KB
/
arena.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
package capnptest01
import (
"errors"
"fmt"
"slices"
capnp "capnproto.org/go/capnp/v3"
)
// ManualSingleSegArena is an Arena implementation that stores message data
// in a continguous slice. Allocation is performed by first allocating a
// new slice and copying existing data. SingleSegment arena does not fail
// unless the caller attempts to access another segment.
type ManualSingleSegArena []byte
// ManualSingleSegment constructs a ManualSingleSegArena from b. b MAY be nil.
// Callers MAY use b to populate the segment for reading, or to reserve
// memory of a specific size.
func ManualSingleSegment(b []byte) *ManualSingleSegArena {
return (*ManualSingleSegArena)(&b)
}
func (ssa ManualSingleSegArena) NumSegments() int64 {
return 1
}
func (ssa ManualSingleSegArena) Data(id capnp.SegmentID) ([]byte, error) {
if id != 0 {
return nil, fmt.Errorf("segment %d requested in single segment arena", id)
}
return ssa, nil
}
func (ssa *ManualSingleSegArena) Allocate(sz capnp.Size, segs map[capnp.SegmentID]*capnp.Segment) (capnp.SegmentID, []byte, error) {
// wordSize is the number of bytes in a Cap'n Proto word.
const wordSize capnp.Size = 8
data := []byte(*ssa)
if segs[0] != nil {
data = segs[0].Data()
}
if len(data)%int(wordSize) != 0 {
return 0, nil, errors.New("segment size is not a multiple of word size")
}
// Pad to the wordsize.
n := capnp.Size(wordSize - 1)
sz = (sz + n) &^ n
*ssa = slices.Grow(*ssa, int(sz))
return 0, *ssa, nil
}
func (ssa ManualSingleSegArena) String() string {
return fmt.Sprintf("single-segment arena [len=%d cap=%d]",
len(ssa), cap(ssa))
}
func (ssa *ManualSingleSegArena) Release() {
if *ssa != nil {
*ssa = []byte(*ssa)[:0]
}
}