decodeCtrlData decodes the control byte and data info at the given offset. Encoding follows the MaxMind DB spec: the control byte's high 3 bits encode the type (or KindExtended if zero, in which case the next byte holds kind-7 and the decoder adds 7 back), and the low 5 bits encode size. Sizes 0..28
(offset uint)
| 137 | // size. Sizes 0..28 are encoded directly; 29 reads 1 extra byte (+29), |
| 138 | // 30 reads 2 (+285), and 31 reads 3 (+65821). |
| 139 | func (d *DataDecoder) decodeCtrlData(offset uint) (Kind, uint, uint, error) { |
| 140 | bufferLen := uint(len(d.buffer)) |
| 141 | newOffset := offset + 1 |
| 142 | if offset >= bufferLen { |
| 143 | return 0, 0, 0, mmdberrors.NewOffsetError() |
| 144 | } |
| 145 | ctrlByte := d.buffer[offset] |
| 146 | |
| 147 | kindNum := Kind(ctrlByte >> 5) |
| 148 | if kindNum == KindExtended { |
| 149 | if newOffset >= bufferLen { |
| 150 | return 0, 0, 0, mmdberrors.NewOffsetError() |
| 151 | } |
| 152 | kindNum = Kind(d.buffer[newOffset] + 7) |
| 153 | newOffset++ |
| 154 | } |
| 155 | |
| 156 | size := uint(ctrlByte & 0x1f) |
| 157 | if size < 29 { |
| 158 | return kindNum, size, newOffset, nil |
| 159 | } |
| 160 | |
| 161 | endOffset := newOffset + size - 28 |
| 162 | if endOffset > bufferLen { |
| 163 | return 0, 0, 0, mmdberrors.NewOffsetError() |
| 164 | } |
| 165 | |
| 166 | switch size { |
| 167 | case 29: |
| 168 | return kindNum, 29 + uint(d.buffer[newOffset]), newOffset + 1, nil |
| 169 | case 30: |
| 170 | value := uint(d.buffer[newOffset])<<8 | uint(d.buffer[newOffset+1]) |
| 171 | return kindNum, 285 + value, endOffset, nil |
| 172 | default: // size == 31 |
| 173 | value := uint(d.buffer[newOffset])<<16 | |
| 174 | uint(d.buffer[newOffset+1])<<8 | |
| 175 | uint(d.buffer[newOffset+2]) |
| 176 | return kindNum, 65821 + value, endOffset, nil |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | // decodeBytes decodes a byte slice from the given offset with the given size. |
| 181 | func (d *DataDecoder) decodeBytes(size, offset uint) ([]byte, uint, error) { |