Skip to content

Commit

Permalink
Merge pull request #263 from capnproto/feature/expose-arena-impl
Browse files Browse the repository at this point in the history
Export concrete arena types.
  • Loading branch information
zenhack authored Jul 13, 2022
2 parents a16baf1 + d536be7 commit df17131
Showing 1 changed file with 28 additions and 26 deletions.
54 changes: 28 additions & 26 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,30 +384,31 @@ type Arena interface {
Allocate(minsz Size, segs map[SegmentID]*Segment) (SegmentID, []byte, error)
}

type singleSegmentArena []byte
// SingleSegmentArena 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 SingleSegmentArena []byte

// SingleSegment returns a new arena with an expanding single-segment
// buffer. b can be used to populate the segment for reading or to
// reserve memory of a specific size. A SingleSegment arena does not
// return errors unless you attempt to access another segment.
func SingleSegment(b []byte) Arena {
ssa := new(singleSegmentArena)
*ssa = b
return ssa
// SingleSegment constructs a SingleSegmentArena 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 SingleSegment(b []byte) *SingleSegmentArena {
return (*SingleSegmentArena)(&b)
}

func (ssa *singleSegmentArena) NumSegments() int64 {
func (ssa SingleSegmentArena) NumSegments() int64 {
return 1
}

func (ssa *singleSegmentArena) Data(id SegmentID) ([]byte, error) {
func (ssa SingleSegmentArena) Data(id SegmentID) ([]byte, error) {
if id != 0 {
return nil, errorf("segment %d requested in single segment arena", id)
}
return *ssa, nil
return ssa, nil
}

func (ssa *singleSegmentArena) Allocate(sz Size, segs map[SegmentID]*Segment) (SegmentID, []byte, error) {
func (ssa *SingleSegmentArena) Allocate(sz Size, segs map[SegmentID]*Segment) (SegmentID, []byte, error) {
data := []byte(*ssa)
if segs[0] != nil {
data = segs[0].data
Expand All @@ -428,8 +429,8 @@ func (ssa *singleSegmentArena) Allocate(sz Size, segs map[SegmentID]*Segment) (S
return 0, *ssa, nil
}

func (ssa *singleSegmentArena) String() string {
return fmt.Sprintf("single-segment arena [len=%d cap=%d]", len(*ssa), cap(*ssa))
func (ssa SingleSegmentArena) String() string {
return fmt.Sprintf("single-segment arena [len=%d cap=%d]", len(ssa), cap(ssa))
}

type roSingleSegment []byte
Expand All @@ -453,15 +454,16 @@ func (ss roSingleSegment) String() string {
return fmt.Sprintf("read-only single-segment arena [len=%d]", len(ss))
}

type multiSegmentArena [][]byte
// MultiSegment is an arena that stores object data across multiple []byte
// buffers, allocating new buffers of exponentially-increasing size when
// full. This avoids the potentially-expensive slice copying of SingleSegment.
type MultiSegmentArena [][]byte

// MultiSegment returns a new arena that allocates new segments when
// they are full. b can be used to populate the buffer for reading or
// to reserve memory of a specific size.
func MultiSegment(b [][]byte) Arena {
msa := new(multiSegmentArena)
*msa = b
return msa
// they are full. b MAY be nil. Callers MAY use b to populate the
// buffer for reading or to reserve memory of a specific size.
func MultiSegment(b [][]byte) *MultiSegmentArena {
return (*MultiSegmentArena)(&b)
}

// demuxArena slices b into a multi-segment arena. It assumes that
Expand All @@ -482,18 +484,18 @@ func demuxArena(hdr streamHeader, data []byte) (Arena, error) {
return MultiSegment(segs), nil
}

func (msa *multiSegmentArena) NumSegments() int64 {
func (msa *MultiSegmentArena) NumSegments() int64 {
return int64(len(*msa))
}

func (msa *multiSegmentArena) Data(id SegmentID) ([]byte, error) {
func (msa *MultiSegmentArena) Data(id SegmentID) ([]byte, error) {
if int64(id) >= int64(len(*msa)) {
return nil, errorf("segment %d requested (arena only has %d segments)", id, len(*msa))
}
return (*msa)[id], nil
}

func (msa *multiSegmentArena) Allocate(sz Size, segs map[SegmentID]*Segment) (SegmentID, []byte, error) {
func (msa *MultiSegmentArena) Allocate(sz Size, segs map[SegmentID]*Segment) (SegmentID, []byte, error) {
var total int64
for i, data := range *msa {
id := SegmentID(i)
Expand All @@ -519,7 +521,7 @@ func (msa *multiSegmentArena) Allocate(sz Size, segs map[SegmentID]*Segment) (Se
return id, buf, nil
}

func (msa *multiSegmentArena) String() string {
func (msa *MultiSegmentArena) String() string {
return fmt.Sprintf("multi-segment arena [%d segments]", len(*msa))
}

Expand Down

0 comments on commit df17131

Please sign in to comment.