| 77 | } |
| 78 | |
| 79 | func (e *Encoder) packBlock() { |
| 80 | if len(e.uids) == 0 { |
| 81 | return |
| 82 | } |
| 83 | |
| 84 | // Allocate blocks manually. |
| 85 | b := e.Alloc.AllocateAligned(blockSize) |
| 86 | block := (*UidBlock)(unsafe.Pointer(&b[0])) |
| 87 | |
| 88 | block.Base = e.uids[0] |
| 89 | block.NumUids = uint32(len(e.uids)) |
| 90 | |
| 91 | // block := &UidBlock{Base: e.uids[0], NumUids: uint32(len(e.uids))} |
| 92 | last := e.uids[0] |
| 93 | e.uids = e.uids[1:] |
| 94 | |
| 95 | e.buf.Reset() |
| 96 | buf := make([]byte, 17) |
| 97 | tmpUids := make([]uint32, 4) |
| 98 | for { |
| 99 | for i := 0; i < 4; i++ { |
| 100 | if i >= len(e.uids) { |
| 101 | // Padding with '0' because Encode4 encodes only in batch of 4. |
| 102 | tmpUids[i] = 0 |
| 103 | } else { |
| 104 | tmpUids[i] = uint32(e.uids[i] - last) |
| 105 | last = e.uids[i] |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | data := groupvarint.Encode4(buf, tmpUids) |
| 110 | Check2(e.buf.Write(data)) |
| 111 | |
| 112 | // e.uids has ended and we have padded tmpUids with 0s |
| 113 | if len(e.uids) <= 4 { |
| 114 | e.uids = e.uids[:0] |
| 115 | break |
| 116 | } |
| 117 | e.uids = e.uids[4:] |
| 118 | } |
| 119 | |
| 120 | sz := len(e.buf.Bytes()) |
| 121 | block.Deltas = e.Alloc.Allocate(sz) |
| 122 | AssertTrue(sz == copy(block.Deltas, e.buf.Bytes())) |
| 123 | e.pack.Blocks = append(e.pack.Blocks, block) |
| 124 | } |
| 125 | |
| 126 | var tagEncoder string = "enc" |
| 127 | |