| 55 | } |
| 56 | |
| 57 | func (e *Encoder) packBlock() { |
| 58 | if len(e.uids) == 0 { |
| 59 | return |
| 60 | } |
| 61 | |
| 62 | // Allocate blocks manually. |
| 63 | b := e.Alloc.AllocateAligned(blockSize) |
| 64 | block := (*pb.UidBlock)(unsafe.Pointer(&b[0])) |
| 65 | |
| 66 | block.Base = e.uids[0] |
| 67 | block.NumUids = uint32(len(e.uids)) |
| 68 | |
| 69 | // block := &pb.UidBlock{Base: e.uids[0], NumUids: uint32(len(e.uids))} |
| 70 | last := e.uids[0] |
| 71 | e.uids = e.uids[1:] |
| 72 | |
| 73 | e.buf.Reset() |
| 74 | buf := make([]byte, 17) |
| 75 | tmpUids := make([]uint32, 4) |
| 76 | for { |
| 77 | for i := range 4 { |
| 78 | if i >= len(e.uids) { |
| 79 | // Padding with '0' because Encode4 encodes only in batch of 4. |
| 80 | tmpUids[i] = 0 |
| 81 | } else { |
| 82 | tmpUids[i] = uint32(e.uids[i] - last) |
| 83 | last = e.uids[i] |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | data := groupvarint.Encode4(buf, tmpUids) |
| 88 | x.Check2(e.buf.Write(data)) |
| 89 | |
| 90 | // e.uids has ended and we have padded tmpUids with 0s |
| 91 | if len(e.uids) <= 4 { |
| 92 | e.uids = e.uids[:0] |
| 93 | break |
| 94 | } |
| 95 | e.uids = e.uids[4:] |
| 96 | } |
| 97 | |
| 98 | sz := len(e.buf.Bytes()) |
| 99 | block.Deltas = e.Alloc.Allocate(sz) |
| 100 | x.AssertTrue(sz == copy(block.Deltas, e.buf.Bytes())) |
| 101 | e.pack.Blocks = append(e.pack.Blocks, block) |
| 102 | } |
| 103 | |
| 104 | var tagEncoder = "enc" |
| 105 | |